/* ══════════════════════════════════════════════════════════════════════════
   Handset
   ─────────────────────────────────────────────────────────────────────────
   A phone shell (static/img/handset.png, 444x916) with a real screen painted
   onto the glass. Two screens are built here:

     .hs--ussd   the dialler with the USSD dialogue over it, drawn to match
                 what the simulator actually renders — dimmed dialler behind a
                 white dialogue, near-black message type, orange CANCEL/SEND.
     .hs--sms    the messages thread, for an inbound alert.

   Plain CSS on purpose: it does not go through the Tailwind build, so the
   frame keeps working whether or not app.css is recompiled, and the same
   rules can be pasted into a standalone document.

   Two nested containers do the sizing. .hs is an inline-size container, so
   the frame geometry is a percentage of the frame. .hs-screen is a size
   container, so everything on the glass is a percentage of the SCREEN — 1cqw
   inside the screen is one percent of the display width, not of the frame.
   Change --hs-w and the whole handset scales as one object.

   The display in the shell art is x 21..418, y 27..887 of a 444x916 frame
   with a 30px corner radius. Every percentage on .hs-screen comes from those
   numbers; if the art is replaced, re-measure and update them.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── THE DEVICE ON A DARK GROUND ─────────────────────────────────────────────
   On the dark theme the handset turns white. A black phone on a black page is
   a silhouette: the shell's bezel is the only thing separating the two, and the
   screen — the part actually carrying the product — reads as a hole. Inverting
   the glass makes the device the lit object in the room, which is what it is
   meant to be.

   Only the screen inverts. The shell is a photograph of a real handset and
   stays what it is; a phone with a white body would stop looking like a phone.
   The dialogue stays pure white in both themes, so on this ground it sits on a
   near-white dialler rather than a black one, and its rule and shadow are what
   separate them. */
/* ── THE GLASS IS A LIGHT ISLAND ─────────────────────────────────────────────
   The screens stay white on the dark theme, but the form and the copy on them
   are the app's own markup and were following the document theme — so the
   headline inverted to near-white and landed on white glass at a contrast of
   1.1. Unreadable.

   Re-declaring the palette variables at the screen boundary fixes every one of
   them at once: inside the glass the tokens hold their light values, so the
   form, the labels, the hints and the alerts paint exactly as they do on the
   light theme, and nothing in the markup has to know which theme is running.
   This is the whole reason the palette is variables rather than classes. */
[data-theme="dark"] .hs-screen {
  --c-fog: var(--lt-fog);
  --c-surface: var(--lt-surface);
  --c-ink: var(--lt-ink);
  --c-divider: var(--lt-divider);
  --c-slate-400: var(--lt-slate-400);
  --c-slate-500: var(--lt-slate-500);
  --c-slate-600: var(--lt-slate-600);
  --c-signal-50: var(--lt-signal-50);
  --c-signal-600: var(--lt-signal-600);
  --c-signal-700: var(--lt-signal-700);
  --c-ok: var(--lt-ok);
  --c-warn: var(--lt-warn);
  --c-bad: var(--lt-bad);
  color-scheme: light;
}

[data-theme="dark"] .hs {
  --hs-glass: #ffffff;      /* the screen, now the lit surface   */
  --hs-surface: #f2f4f6;    /* the dialler drawn on it           */
  --hs-fg: #202124;         /* type on the light dialler         */
  --hs-mute: #5c6570;       /* keypad letters, home bar          */
  --hs-digit: #1a56c4;      /* keypad digits, darkened to hold   */
  --hs-call: #1e8e3e;       /* the call button is green either way */
  --hs-rule: #d7dce2;
  --hs-off: #9aa0a6;
  /* A black wash would grey out the very screen we just made white. */
  --hs-scrim: rgba(255, 255, 255, 0.62);

  /* Ink washes now, for the same reason in reverse. Kept a shade lighter than
     the white-on-black values: a dark wash on white reads stronger than a light
     wash on black at the same alpha. */
  --hs-press: rgba(7, 9, 11, 0.07);
  --hs-press-focus: rgba(7, 9, 11, 0.10);
  --hs-press-active: rgba(7, 9, 11, 0.15);
  --hs-hair: rgba(7, 9, 11, 0.10);
}

.hs {
  --hs-w: 300px;

  /* Screen palette, read off the simulator screens themselves. */
  --hs-glass: #000;         /* the phone screen             */
  --hs-surface: #141518;    /* the dialler drawn on it      */
  --hs-fg: #e8eaed;         /* type on the dark dialler     */
  --hs-mute: #9aa0a6;       /* keypad letters, home bar     */
  --hs-digit: #8ab4f8;      /* keypad digits                */
  --hs-call: #1e8e3e;       /* call button                  */
  --hs-card: #fff;          /* the USSD dialogue            */
  --hs-ink: #202124;        /* type inside the dialogue     */
  --hs-rule: #c7cdd4;       /* the rule above the actions   */
  --hs-act: #ff6a00;        /* CANCEL / SEND                */
  --hs-off: #bdc1c6;        /* a disabled action            */

  /* Washes drawn on the glass. They were hardcoded white, which is right on a
     black screen and invisible on a white one — the keypad lost its press
     feedback entirely on the dark theme. Tokenised so they invert with the
     device. */
  --hs-press: rgba(255, 255, 255, 0.08);
  --hs-press-focus: rgba(255, 255, 255, 0.12);
  --hs-press-active: rgba(255, 255, 255, 0.17);
  --hs-hair: rgba(255, 255, 255, 0.10);

  container-type: inline-size;
  position: relative;
  /* width + max-width rather than min(--hs-w, 100%): a percentage against a
     shrink-to-fit parent — a flex item sized by its content, as in the auth
     panel — resolves to zero and collapses the frame. This clamps the same
     way but keeps the width definite. */
  width: var(--hs-w);
  max-width: 100%;
  aspect-ratio: 444 / 916;
  margin-inline: auto;
  -webkit-tap-highlight-color: transparent;
}

.hs--sm { --hs-w: 250px; }
.hs--md { --hs-w: 290px; }
.hs--lg { --hs-w: 330px; }

/* The homepage hero, where the phone is the argument and had far more column
   than it was using. Fluid rather than a fourth fixed step, so it fills the
   column it is given.

   Width is derived from the WINDOW HEIGHT as well as its width, because the
   hero is meant to land inside the fold and this frame is 916/444 — a little
   more width costs twice as much height. A phone sized on width alone was
   860px tall on a 980px laptop screen and pushed its own section past the
   bottom of the window. The height term keeps it as large as the fold allows
   and no larger. The 194px is measured, not guessed: 69px of header including
   its border, 40+40 of section padding, a 29px caption with a 12px margin, and
   the section's own bottom border, plus three to spare. The floor wins on a
   very short window, where fitting the fold would mean a phone too small to
   read the menu on — legibility beats the fold at that point. */
/* The platform page, where the handset carries the whole argument.

   Height-aware, because width alone is not enough: a 916/444 frame at 440px
   wide stands 908px tall, taller than the window it has to be seen in, and its
   top ends up behind the sticky header with no scroll position that shows the
   whole device. Every handset on the site is sized against the window. */
.hs--wide {
  --hs-w: min(clamp(300px, 33vw, 440px), calc((var(--app-vh, 100vh) - 150px) * 444 / 916));
  --hs-w: min(clamp(300px, 33vw, 440px), calc((var(--app-vh, 100svh) - 150px) * 444 / 916));
}

.hs--hero {
  --hs-w: clamp(260px, min(30vw, calc((var(--app-vh, 100vh) - 194px) * 444 / 916)), 420px);
  --hs-w: clamp(260px, min(30vw, calc((var(--app-vh, 100svh) - 194px) * 444 / 916)), 420px);
}

/* The shell sits under the glass so the screen stays interactive. */
.hs-shell {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
  /* Follows the alpha channel, so the shadow takes the shape of the body
     instead of a rectangle behind it. */
  filter: drop-shadow(0 18px 34px rgba(7, 9, 11, 0.18));
}

/* ── THE WHITE COVER ────────────────────────────────────────────────────────
   On the dark theme the whole device turns white, cover included, not just the
   glass. The shell is a render of a dark handset, so the light one is the same
   render inverted — a white phone is not a dark phone lightened, it is the same
   object lit the other way round, with the body bright and the seams and
   chamfers reading dark. Swapped through content: rather than a second <img>,
   so no macro has to know which theme is running.

   The dark ground eats a drop shadow, so the cover gets a faint halo instead —
   otherwise a white phone on black has a hard cut for an edge. */
[data-theme="dark"] .hs-shell {
  content: url("../img/handset-light.png");
  filter: drop-shadow(0 0 30px rgba(255, 255, 255, 0.10));
}

.hs-screen {
  container-type: size;
  position: absolute;
  left: 4.72973%;
  top: 2.94760%;
  width: 89.63964%;
  height: 93.99563%;
  border-radius: 6.75676cqw;   /* resolves against .hs — 30 of 444 */
  background: var(--hs-glass);
  overflow: hidden;
  font-family: Inter, ui-sans-serif, system-ui, sans-serif;
}

.hs--sms .hs-screen { background: var(--hs-card); }

.hs-screen svg { display: block; }

/* The app-wide focus ring is a box-shadow drawn around the element's box, which
   on a round key paints a rectangle. Every control on the glass shows focus its
   own way — the keys by filling their circle, the reply field by colouring the
   line beneath it — so the shared ring is cancelled here. */
.hs button:focus-visible,
.hs input:focus-visible { box-shadow: none; }

/* ── Status bar ─────────────────────────────────────────────────────────── */
.hs-status {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 4;
  height: 7.5cqw;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2cqw;
  padding: 0 4.5cqw;
  font-size: 3.4cqw;
  line-height: 1;
  color: var(--hs-fg);
  white-space: nowrap;
}

.hs--sms .hs-status { color: var(--hs-ink); }

.hs-status > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.hs-meters { display: flex; align-items: center; gap: 1.6cqw; }
.hs-meters svg { width: 3.4cqw; height: 3.4cqw; fill: currentColor; }

/* ══ THE DIALLER ═══════════════════════════════════════════════════════════ */
.hs-dialer {
  position: absolute;
  inset: 7.5cqw 0 0 0;
  display: flex;
  flex-direction: column;
  background: var(--hs-surface);
  color: var(--hs-fg);
}

/* As an input it inherits none of the screen's type, so everything the old
   paragraph got for free is stated here. */
input.hs-dialed {
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--hs-hair);
  color: var(--hs-fg);
  font-family: inherit;
  font-weight: inherit;
  caret-color: var(--hs-act);
  outline: none;
}

input.hs-dialed::placeholder { color: var(--hs-off); }
input.hs-dialed:disabled { opacity: 0.55; }

/* Selection on the glass. The site's peach highlight is tuned for white pages
   and painted a washed-out block across the dialled code, so inside the handset
   the selection takes the screen's own accent: solid orange on the dark dialler,
   and a soft orange wash on the white document screens, where the text is dark
   and a solid fill would fight it. */
.hs-screen ::selection { background: var(--hs-act); color: var(--hs-glass); }
.hs-screen ::-moz-selection { background: var(--hs-act); color: var(--hs-glass); }
.hs--sms .hs-screen ::selection,
.hs--deck .hs-screen ::selection { background: rgba(255, 106, 0, 0.22); color: var(--hs-ink); }
.hs--sms .hs-screen ::-moz-selection,
.hs--deck .hs-screen ::-moz-selection { background: rgba(255, 106, 0, 0.22); color: var(--hs-ink); }

.hs-dialed {
  margin: auto 0 0;
  min-height: 7.4cqw;
  padding: 4cqw 4cqw;
  text-align: center;
  font-size: 7.4cqw;
  line-height: 1.1;
  letter-spacing: 0.01em;
  border-bottom: 1px solid var(--hs-hair);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hs-pad { display: grid; grid-template-columns: repeat(3, 1fr); }

.hs-key {
  height: 17cqw;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
}

/* The highlight is the digit's own box, not the cell's. A cell is twice as wide
   as it is tall, so a radius on the cell gave a stretched oval; and the letter
   row is empty on 1, * and #, which shifted those digits off centre. Fixing the
   size of both rows makes every key identical: the same circle, the same
   distance from the glyph on all four sides. */
.hs-key b {
  display: grid;
  place-items: center;
  box-sizing: border-box;
  width: 13cqw;
  height: 13cqw;
  /* A digit's ink sits half a pixel above the middle of its line box, because
     the box reserves descender space the digit never uses. Half of this padding
     moves the glyph down by exactly that much, so the ring is the same distance
     from the number top and bottom. Measured, not guessed. */
  padding-top: 0.34cqw;
  border-radius: 50%;
  font-size: 8.4cqw;
  font-weight: 400;
  line-height: 1;
  color: var(--hs-digit);
  background: transparent;
  transition: background-color 0.12s ease;
}

.hs-key i {
  height: 3.2cqw;
  line-height: 3.2cqw;
  font-size: 2.9cqw;
  font-style: normal;
  letter-spacing: 0.14em;
  color: var(--hs-mute);
}

button.hs-key { cursor: pointer; }
button.hs-key:hover b { background: var(--hs-press); }
button.hs-key:active b { background: var(--hs-press-active); }

/* No accent ring: an orange circle on the last-touched key reads as a pressed
   state that was never pressed. The neutral fill is indicator enough. */
button.hs-key:focus { outline: none; }
button.hs-key:focus-visible { outline: none; }
button.hs-key:focus-visible b { background: var(--hs-press-focus); }

.hs-key--sym b { color: var(--hs-fg); }

/* The asterisk's ink sits near the top of its em box — it is drawn as a raised
   glyph — so it takes a larger share of the padding to land in the middle. */
.hs-key--star b { padding-top: 2.37cqw; }

.hs-call-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  justify-items: center;
}

.hs-back {
  padding: 3cqw;
  border: 0;
  background: none;
  border-radius: 50%;
  cursor: pointer;
  justify-self: start;
  transition: background-color 0.12s ease;
}

.hs-back:hover { background: var(--hs-press); }
.hs-back:focus-visible { outline: 2px solid var(--hs-act); outline-offset: -2px; }
.hs-back svg { width: 6.4cqw; height: 6.4cqw; fill: var(--hs-mute); }

.hs-fab {
  width: 17cqw;
  height: 17cqw;
  margin: 3.5cqw auto 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--hs-call);
  display: grid;
  place-items: center;
  transition: opacity 0.15s ease;
}

button.hs-fab { cursor: pointer; }
button.hs-fab:disabled { opacity: 0.4; cursor: not-allowed; }
button.hs-fab:focus-visible { outline: 2px solid var(--hs-act); outline-offset: 2px; }
.hs-fab svg { width: 7.6cqw; height: 7.6cqw; fill: #fff; }

.hs-nav {
  height: 9cqw;
  margin-top: 3cqw;
  border-top: 1px solid var(--hs-hair);
  display: grid;
  place-items: center;
}

.hs-nav svg { width: 5cqw; height: 5cqw; fill: var(--hs-mute); }

/* ── Call states ────────────────────────────────────────────────────────────
   A marketing handset (.hs without .hs--live) always shows the dialogue — it is
   a picture of a session. A live one starts on the dialler and only raises the
   dialogue once a call is placed, then swaps CANCEL/SEND for OK when the
   session closes. The JS toggles is-session / is-ended on the frame. */
.hs--live .hs-scrim,
.hs--live .hs-dialog { display: none; }

.hs--live.is-session .hs-scrim,
.hs--live.is-ended .hs-scrim { display: block; }

.hs--live.is-session .hs-dialog,
.hs--live.is-ended .hs-dialog { display: flex; }

.hs--live .hs-act--done { display: none; }
.hs--live.is-ended .hs-field,
.hs--live.is-ended .hs-act--live { display: none; }
.hs--live.is-ended .hs-act--done { display: inline-block; }
/* A closed session shows one button and no field, so the rule has nothing left
   to divide. */
.hs--live.is-ended .hs-actions { border-top: 0; padding-top: 1cqw; }

/* ── The dim behind the dialogue ────────────────────────────────────────── */
.hs-scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--hs-scrim, rgba(0, 0, 0, 0.5));
  /* The keypad underneath stays clickable — it is the reply pad once a
     session is open, which is what the JS expects. */
  pointer-events: none;
}

/* ── The USSD dialogue ──────────────────────────────────────────────────── */
.hs-dialog {
  position: absolute;
  z-index: 3;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 86%;
  max-height: 76%;
  display: flex;
  flex-direction: column;
  padding: 5.5cqw 5.5cqw 4cqw;
  border-radius: 3.4cqw;
  background: var(--hs-card);
  box-shadow: 0 6cqw 18cqw rgba(0, 0, 0, 0.45);
}

.hs-msg { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }

/* ...but only in the simulator, where the network's reply can be any length.
   Everywhere else the dialogue is authored, fixed, and meant to be read whole,
   so a scrollbar over it is a defect. The homepage menu was sitting at exactly
   its content height with no slack — one font metric away from a scrollbar
   appearing over the nine lines it exists to show. Off the simulator the
   message sizes to its text: min-height:auto stops the flex parent compressing
   it, and the dialogue grows to fit instead of capping and scrolling. */
.hs:not(.hs--live) .hs-msg {
  min-height: auto;
  overflow-y: visible;
}

.hs:not(.hs--live) .hs-dialog { max-height: 92%; }

/* The simulator rewrites the pre's className on every exchange, so the pre
   carries no layout and no colour of its own — both live here, where the
   repaint cannot reach them. Two classes outrank the Tailwind colour utility
   the repaint applies. */
.hs .term {
  margin: 0;
  /* Fully specified rather than leaning on app.css, so the component drops
     into a standalone document unchanged. */
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: 4.3cqw;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  color: var(--hs-ink);
}

.hs-field {
  flex-shrink: 0;
  width: 100%;
  height: 9cqw;
  margin-top: 4.5cqw;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  /* No rule of its own. The line above the actions sits directly beneath this
     field and serves as its underline — one line, not two. */
  color: var(--hs-ink);
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: 4.3cqw;
  transition: box-shadow 0.15s ease;
}

.hs-field::placeholder { color: var(--hs-off); }
.hs-field:focus { outline: none; }
.hs-field:disabled { opacity: 0.5; cursor: not-allowed; }

/* Focus colours the shared line instead, so the field still shows it is live. */
.hs-field:focus + .hs-actions { border-top-color: var(--hs-act); }

.hs-actions {
  flex-shrink: 0;
  display: flex;
  justify-content: flex-end;
  gap: 6cqw;
  margin-top: 2.4cqw;
  padding-top: 3.4cqw;
  border-top: 1px solid var(--hs-rule);
  transition: border-color 0.15s ease;
}

.hs-act {
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 3.9cqw;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--hs-act);
  transition: opacity 0.15s ease;
}

button.hs-act { cursor: pointer; }
button.hs-act:hover { opacity: 0.75; }
button.hs-act:disabled { color: var(--hs-off); cursor: not-allowed; opacity: 1; }
button.hs-act:focus-visible { outline: 2px solid var(--hs-act); outline-offset: 3px; }

/* ══ THE MESSAGES THREAD ═══════════════════════════════════════════════════ */
.hs-sms {
  position: absolute;
  inset: 7.5cqw 0 0 0;
  display: flex;
  flex-direction: column;
  color: var(--hs-ink);
}

.hs-sms-head {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 4.5cqw;
  padding: 3.5cqw 5cqw;
  font-size: 5.2cqw;
  line-height: 1.2;
}

.hs-sms-head svg { width: 5.6cqw; height: 5.6cqw; fill: var(--hs-ink); flex-shrink: 0; }

.hs-thread {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 2cqw;
  padding: 4cqw 4.5cqw;
}

.hs-line { display: flex; align-items: flex-end; gap: 2.5cqw; }

.hs-avatar {
  flex-shrink: 0;
  width: 9cqw;
  height: 9cqw;
  border-radius: 50%;
  background: #7b4fd8;
  display: grid;
  place-items: center;
}

.hs-avatar svg { width: 5.4cqw; height: 5.4cqw; fill: #fff; }

.hs-bubble {
  max-width: 80%;
  padding: 3.4cqw 4cqw;
  border-radius: 4.6cqw;
  background: #edf0f4;
  font-size: 4.1cqw;
  line-height: 1.5;
}

.hs-sms-nav {
  flex-shrink: 0;
  height: 10cqw;
  border-top: 1px solid #e4e7eb;
  display: grid;
  place-items: center;
}

.hs-sms-nav svg { width: 5cqw; height: 5cqw; fill: #5f6368; }

/* ── Caption under the frame ────────────────────────────────────────────── */
.hs-cap {
  max-width: min(var(--hs-w), 100%);
  margin: 0.75rem auto 0;
  text-align: center;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: 10px;
  line-height: 1.45;
  color: #8b939e;
}
/* ══ THE AUTH DECK — TWO HANDSETS, ONE PAGE ════════════════════════════════
   Sign-in, sign-up and change-password put two identical phones on a black
   page: the left one carries the argument, the right one carries the form.
   Nothing else is drawn. No cards, no columns, no second background — the page
   is black and the only lit surfaces are the two screens.

   The two frames are the same object by construction, not by coincidence: both
   read --hs-w from the same expression below, so there is no way for one to
   drift from the other. The shell art is back, because the frame is a fixed
   444x916 portrait again and the render is better than anything drawn in CSS.

   Everything on both screens is sized in cqw — a share of the SCREEN width —
   so the two phones scale as one. The form is the reason the numbers are also
   clamped: it is built from the app's own .input, .btn and .field, which are
   specified in pixels, and the clamps let the container-relative sizes land on
   those pixel values at a normal window while still following the phone up and
   down. Below the ceiling and above the floor, the form you see is the form the
   rest of the app uses.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The page. This is the only background in the auth layout. */
/* The auth stage follows the theme: white on light, pure black on dark — the
   same black as the dark hero, so the product has one black and not three that
   nearly match. On the light ground the handsets keep their dark shells, which
   is what separates them from the page; on the dark ground the shells invert
   with everything else and the screens become the lit surfaces. */
/* svh, and a height rather than a min-height: with min-height:100vh the stage
   could stand taller than the small viewport and the page would scroll by the
   difference, which is exactly what "the phone must stay put" rules out. */
.hs-stage {
  height: var(--app-vh, 100vh);
  height: var(--app-vh, 100svh);
  overflow: hidden;
  background: #fff;
}

[data-theme="dark"] .hs-stage { background: #000; }

/* Floating theme control — these pages have no header to hold it. */
/* The theme control is docked to one place on every page: the top right of the
   window, at the dashboard topbar's gutter. It sits outside the header's centred
   shell so its distance from the edge does not change with the layout, and the
   headers reserve room for it so nothing can slide underneath.

   .hs-theme is the auth pages' wrapper and now needs no offsets of its own. */
.theme-dock {
  position: fixed;
  top: 10px;
  right: 16px;
  z-index: 60;
}

@media (min-width: 640px) {
  .theme-dock { right: 24px; }
}

/* Room for the dock: the button is 38px wide, plus a gap. Applied where other
   controls would otherwise reach the same corner. */
.theme-dock-space { padding-right: 50px; }

@media (min-width: 640px) {
  .theme-dock-space { padding-right: 58px; }
}

.hs-theme { position: static; }

.hs-theme .theme-toggle { color: #5c6570; }
.hs-theme .theme-toggle:hover { color: #07090b; }
[data-theme="dark"] .hs-theme .theme-toggle { color: #9aa0a6; }
[data-theme="dark"] .hs-theme .theme-toggle:hover { color: #ffffff; }

.hs-pair {
  --hs-gx: clamp(12px, 1.6vw, 34px);
  --hs-gy: clamp(12px, calc(var(--app-vh, 100vh) * 0.022), 34px);
  --hs-gap: clamp(14px, 2.4vw, 56px);

  container-type: size;
  box-sizing: border-box;
  /* svh, not dvh. dvh follows the browser chrome and the on-screen keyboard, so
     a phone re-sized the whole handset the moment a field took focus and again
     when it lost it — the device visibly jumped while you were typing into it.
     svh is a settled value: it does not move. */
  height: var(--app-vh, 100svh);
  display: grid;
  grid-template-columns: 1fr 1fr;
  place-items: center;
  gap: var(--hs-gap);
  padding: var(--hs-gy) var(--hs-gx);
}

/* One phone, as tall as the page allows, unless its half is too narrow to hold
   a phone that tall — in which case the half sets the size instead. Both frames
   evaluate this identically, so they are always the same size. */
.hs--deck {
  --hs-slot: calc((100cqw - var(--hs-gap)) / 2);
  --hs-w: min(var(--hs-slot), calc(100cqh * 444 / 916));
}

.hs--deck .hs-screen { background: var(--hs-card); }

/* ── The chrome both screens share ──────────────────────────────────────── */
/* Status bar, body, home bar, in flow. The middle band takes what is left and
   scrolls on its own if it has to — which the sign-up form does, since it is
   longer than any phone screen. Pinning the bars instead of placing them would
   mean the two screens could disagree about where the glass begins and ends. */
.hs-deck .hidden { display: none; }

.hs-deck {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  /* --c-ink, not --hs-ink: inside a device the island pins this to the light
     value, and on a phone — where the frame is gone and the screen is the page —
     it follows the document theme instead. One declaration, both cases. */
  color: rgb(var(--c-ink));
}

.hs--deck .hs-status {
  position: static;
  flex-shrink: 0;
  height: 7.5cqw;
  color: var(--hs-ink);
}

.hs-deck-main {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: #c7cdd4 transparent;
}

.hs-deck-main::-webkit-scrollbar { width: 1.3cqw; }
.hs-deck-main::-webkit-scrollbar-track { background: transparent; }
.hs-deck-main::-webkit-scrollbar-thumb { background: #c7cdd4; border-radius: 99px; }

/* Sign-up is longer than any phone screen, so it runs under the home bar. The
   fade says the form continues rather than letting it look truncated. It is on
   the form screen only — opposite, the message sits at the very bottom of the
   glass and must not be washed out — and it costs nothing on a short form,
   where that strip of glass is empty anyway. */
.hs-form-phone .hs-deck::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 10cqw;
  height: 7cqw;
  pointer-events: none;
  background: linear-gradient(to top, var(--hs-card), rgba(255, 255, 255, 0));
}

.hs--deck .hs-sms-nav {
  position: static;
  flex-shrink: 0;
  height: 10cqw;
}

/* The mark, on both screens, and the way back to the public site from both. */
.hs-mark {
  display: flex;
  align-items: center;
  gap: 2.6cqw;
  width: -moz-fit-content;
  width: fit-content;
  color: inherit;
  text-decoration: none;
}

.hs-mark svg { width: 9cqw; height: 9cqw; flex-shrink: 0; }

.hs-mark span {
  font-family: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  font-weight: 700;
  font-size: 6cqw;
  letter-spacing: -0.02em;
}

/* No hover state on the mark, on any device: it is a link home and nothing
   else. These two rules exist to defeat a:hover in app.css, which is more
   specific than .hs-mark and would otherwise tint the wordmark orange. The
   focus ring is left alone — that is a keyboard affordance, not a hover. */
a.hs-mark:hover,
a.hs-mark:focus,
a.hs-mark:active { color: inherit; }

a.hs-mark:hover span,
a.hs-mark:focus span,
a.hs-mark:active span { color: inherit; }

a.hs-mark:focus-visible { border-radius: 2cqw; }

/* ══ SCREEN ONE — THE ARGUMENT ═════════════════════════════════════════════ */
.hs-say {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 5cqw 6cqw 0;
}

/* The slack sits above and below the claim rather than pooling into one gap
   over the message, so the screen stays composed at any height. */
.hs-say-body {
  margin-block: auto;
  padding-block: 3cqw;
}

.hs-panel-kicker {
  margin: 0;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: 3.1cqw;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #db5a00;
}

.hs-panel-head {
  margin: 3.4cqw 0 0;
  font-family: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  font-weight: 700;
  font-size: 7.4cqw;
  line-height: 1.12;
  letter-spacing: -0.03em;
}

.hs-panel-body {
  margin: 4cqw 0 0;
  font-size: 4.1cqw;
  line-height: 1.6;
  color: #3a4250;
}

.hs-panel-stats {
  display: grid;
  grid-template-columns: repeat(3, max-content);
  justify-content: space-between;
  gap: 3cqw;
  margin: 6cqw 0 0;
  padding-top: 5cqw;
  border-top: 1px solid #e4e7eb;
}

.hs-panel-stats dt {
  margin: 0;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: 2.7cqw;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: #8b939e;
}

.hs-panel-stats dd {
  margin: 1.6cqw 0 0;
  font-family: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  font-weight: 600;
  font-size: 4.4cqw;
  letter-spacing: -0.02em;
}

.hs-panel-thread { padding-bottom: 4cqw; }

.hs-panel-from {
  display: flex;
  align-items: center;
  gap: 3cqw;
  padding-bottom: 3.4cqw;
  font-size: 4.2cqw;
  color: var(--hs-ink);
}

.hs-panel-from svg { width: 4.6cqw; height: 4.6cqw; fill: var(--hs-ink); flex-shrink: 0; }
.hs-say .hs-bubble { font-size: 3.8cqw; }

/* ══ SCREEN TWO — THE FORM ═════════════════════════════════════════════════
   The markup is the app's own form, untouched. Only its scale is restated
   here, in cqw, so it grows and shrinks with the handset exactly as the
   argument opposite does. Element selectors inside .hs-form outrank the
   single-class pixel utilities they override. */
.hs-form {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 5cqw 6cqw 6cqw;
  font-size: 3.6cqw;
}

.hs-form-head { flex-shrink: 0; }
/* The auto margins already centre a short form, so this padding only ever adds
   height to a form that is too tall — and change-password was overflowing by a
   dozen pixels, enough to raise a scrollbar on a screen that otherwise fits.
   Kept small for the case where a form ends flush against the home bar. */
.hs-form-body { margin-block: auto; padding-block: 1.5cqw; }

.hs-form h1 {
  margin: 5.5cqw 0 0;
  font-family: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  font-weight: 700;
  font-size: max(20px, 7.4cqw);
  line-height: 1.12;
  letter-spacing: -0.03em;
}

.hs-form h1 + p {
  margin: 1.8cqw 0 6cqw;
  font-size: max(11px, 3.6cqw);
  line-height: 1.5;
}

.hs-form p { font-size: max(10.5px, 3.4cqw); line-height: 1.5; }
.hs-form .hint, .hs-form .err { font-size: max(9.5px, 3cqw); }

.hs-form .field { margin-bottom: 3.2cqw; gap: 1.4cqw; }

.hs-form .field > label,
.hs-form .kicker,
.hs-form .flabel {
  font-size: max(8.5px, 2.7cqw);
  letter-spacing: 0.1em;
}

.hs-form .kicker { margin-bottom: 1cqw; }
.hs-form form > .kicker:not(:first-child) { margin-top: 4.5cqw; }

.hs-form .input,
.hs-form .select,
.hs-form .textarea {
  min-height: max(34px, 11.6cqw);
  padding: 1.8cqw 4.4cqw;
  border-radius: 6cqw;
  font-size: max(11.5px, 3.8cqw);
}

.hs-form .input.pr-11 { padding-right: 11cqw; }

.hs-form .btn {
  min-height: max(34px, 12cqw);
  gap: 2cqw;
  padding-inline: 5cqw;
  border-radius: 6cqw;
  font-size: max(11.5px, 3.8cqw);
}

.hs-form .btn .ico { width: 1em; height: 1em; }

/* The reveal eye is positioned against the field, so it scales with it too. */
.hs-form .btn-icon {
  width: 9cqw !important;
  height: 9cqw !important;
  min-height: 0;
  right: 1.6cqw;
  padding-inline: 0;
}

.hs-form .btn-block { margin-top: 4cqw; }
.hs-form .btn-block + .btn-block { margin-top: 2cqw; }

.hs-form .check { gap: 2.4cqw; margin-top: 2.6cqw; }

.hs-form .check > input[type="checkbox"] {
  width: 4.6cqw;
  height: 4.6cqw;
  min-width: 4.6cqw;
  border-radius: 1.4cqw;
}

.hs-form .check > span { font-size: max(10.5px, 3.4cqw); }

/* The rule and the note under the form. */
.hs-form form + div,
.hs-form form + p {
  margin-top: 6cqw;
  padding-top: 5cqw;
}

.hs-form form + div > p + p { margin-top: 2.4cqw; }

/* Buttons are links here too, and they carry their own chrome; the underline
   below is for inline links in the body copy, not for these. */
.hs-form a.btn { text-decoration: none; }

.hs-form a:not(.hs-mark):not(.btn) {
  color: rgb(var(--c-ink));
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: #d7dce2;
  text-underline-offset: 2px;
}

/* Buttons excluded, as in the rule above: a .btn carries its own hover, and
   tinting its label orange made the same button behave differently inside a
   handset than it does anywhere else on the site. */
.hs-form a:not(.hs-mark):not(.btn):hover { color: rgb(var(--c-signal-600)); }

/* The terms and privacy links carry their own hover from Tailwind; without
   this the block above would repaint them and they would stop matching the
   sign-in link they are meant to look like. */
.hs-form a.hover\:text-signal-600:hover { color: #db5a00; }
.hs-form .btn { text-decoration: none; }

/* Password strength meter and its checklist. */
.hs-form #pw-meter { gap: 1cqw; margin-top: 2.4cqw; }
.hs-form #pw-meter > span { height: 1.1cqw; }
.hs-form #pw-meter + ul { margin-top: 2.4cqw; gap: 1cqw 3cqw; }
.hs-form #pw-meter + ul li { gap: 1.4cqw; font-size: max(9px, 2.9cqw); }
.hs-form .dot { width: 1.7cqw; height: 1.7cqw; }

.hs-form .alert {
  gap: 2.4cqw;
  margin-bottom: 4cqw;
  padding: 2.6cqw 3.6cqw;
  border-radius: 4cqw;
  font-size: max(10.5px, 3.3cqw);
}

.hs-form .alert .ico { width: 1.1em; height: 1.1em; }


/* Sign-up puts sector/county and username/phone side by side. That is right on
   a wide phone and cramped on a narrow one — at a 250px glass the placeholders
   were being cut mid-word — so the pair collapses to one field per row below
   the width where both still read. */
@container (max-width: 320px) {
  .hs-form form > div.grid { grid-template-columns: 1fr; }
}
/* ══ THE LEGAL DECK — A DOCUMENT ON ONE BIG SCREEN ═════════════════════════
   Terms and privacy get the same handset the rest of the site uses, sized to
   the window instead of to a column. The glass scrolls; the page does not, so
   the device stays whole while the document moves inside it. */
/* The document pages scroll normally: the handset sits in the flow and moves
   with the page, and the footer follows it. No background either — an opaque
   stage left a pale band under the device on a phone. */
.legal-stage {
  --legal-pad: clamp(16px, calc(var(--app-vh, 100vh) * 0.03), 40px);
  /* The same ground as the footer below it. The page ground is fog and the
     footer is surface, so without this the two meet in a hard seam a few
     centimetres under the device, which reads as a pale band stuck to the
     bottom of the phone. */
  background: rgb(var(--c-surface));
  display: grid;
  place-items: center;
  padding: var(--legal-pad) clamp(12px, 2vw, 32px);
  min-height: calc(var(--app-vh, 100vh) - 69px);
  min-height: calc(var(--app-vh, 100svh) - 69px);
}

/* Sized off the viewport, not off the stage. A container-relative height was
   the obvious way to write this and it resolved to zero: cqh needs the
   container's block size to be definite in a way min-height on a grid does not
   give it, so the frame collapsed and the page rendered empty. The same svh
   arithmetic the hero uses is deterministic and has no such edge. */
.hs--legal,
.legal-stage .hs--deck {
  --hs-w: min(92vw, 560px, calc((var(--app-vh, 100vh) - 69px - 2 * var(--legal-pad) - 8px) * 444 / 916));
  --hs-w: min(92vw, 560px, calc((var(--app-vh, 100svh) - 69px - 2 * var(--legal-pad) - 8px) * 444 / 916));
}

.hs-legal {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 5cqw 6.5cqw 6cqw;
  color: var(--hs-ink);
}

/* The title is the first thing on the glass, so the screen padding is its only
   offset. */
.hs-legal-title {
  margin: 0;
  font-family: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  font-weight: 700;
  font-size: max(21px, 7.4cqw);
  line-height: 1.12;
  letter-spacing: -0.03em;
  color: rgb(var(--c-ink));
}

.hs-legal-updated {
  margin: 1.6cqw 0 0;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: max(9.5px, 2.7cqw);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* slate-500, not 400: at this size 400 lands on 3.1 against white glass. */
  color: rgb(var(--c-slate-500));
}

.hs-legal-body { margin-top: 5cqw; }

/* A form on a document screen. .hs-form does this work for the auth decks; the
   contact form is the same markup on the same glass, so it borrows the rules
   rather than growing a second set that would drift from them. */
.hs-form-fields { margin-top: 5cqw; }

/* The confirmation after a message is handed to the mail client. It replaces
   the form rather than sitting under it, so the screen shows one thing. */
.hs-sent {
  margin: 8cqw 0 0;
  padding: 5cqw;
  border: 1px solid rgb(var(--c-divider));
  border-radius: 4cqw;
  background: rgb(var(--c-fog));
  font-size: max(12px, 3.6cqw);
  line-height: 1.6;
  color: rgb(var(--c-ink));
}
.hs-form-fields .field { margin-bottom: 3.2cqw; gap: 1.4cqw; }
.hs-form-fields .field > label { font-size: max(8.5px, 2.7cqw); letter-spacing: 0.1em; }
.hs-form-fields .input,
.hs-form-fields .select,
.hs-form-fields .textarea {
  min-height: max(34px, 11.6cqw);
  padding: 1.8cqw 4.4cqw;
  border-radius: 6cqw;
  font-size: max(11.5px, 3.8cqw);
}
.hs-form-fields .textarea { min-height: max(90px, 30cqw); }
.hs-form-fields .hint, .hs-form-fields .err { font-size: max(9.5px, 3cqw); }
.hs-form-fields .btn {
  min-height: max(34px, 12cqw);
  gap: 2cqw;
  border-radius: 6cqw;
  font-size: max(11.5px, 3.8cqw);
  margin-top: 4cqw;
}

.hs-legal-body h2 {
  margin: 6.5cqw 0 0;
  font-family: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  font-weight: 700;
  font-size: max(14px, 4.3cqw);
  letter-spacing: -0.02em;
  color: rgb(var(--c-ink));
}

.hs-legal-body h2:first-child { margin-top: 0; }

.hs-legal-body p,
.hs-legal-body li {
  margin: 2.6cqw 0 0;
  font-size: max(12px, 3.5cqw);
  line-height: 1.62;
  color: rgb(var(--c-slate-600));
}

/* The base layer strips list markers site-wide, which is right for navigation
   and wrong for a document: these are enumerated obligations and need to read
   as a list. */
.hs-legal-body ul {
  margin: 2.6cqw 0 0;
  padding-left: 5cqw;
  list-style: disc;
}

.hs-legal-body li::marker { color: rgb(var(--c-slate-400)); }

/* ── ON-GLASS PIECES THE DOCUMENT PAGES ADD ─────────────────────────────────
   Inline code, and the status page's live check list. Colours come from the
   palette variables rather than hex, so they hold inside a white device on the
   dark theme and follow the page on a phone, where the frame is gone. */
.hs-legal-body .hs-mono,
.hs-legal-body ul .hs-mono {
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: 0.92em;
  padding: 0.1em 0.36em;
  border-radius: 0.35em;
  background: rgb(var(--c-fog));
  color: rgb(var(--c-ink));
}

.hs-status-line {
  margin: 0 0 4cqw;
  font-family: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  font-weight: 600;
  font-size: max(13px, 4cqw);
  letter-spacing: -0.01em;
}

.hs-status-ok { color: rgb(var(--c-ok)); }
.hs-status-degraded { color: rgb(var(--c-warn)); }
.hs-status-down { color: rgb(var(--c-bad)); }

.hs-checks {
  margin: 0 0 6cqw;
  border-top: 1px solid rgb(var(--c-divider));
}

.hs-check {
  padding: 3cqw 0;
  border-bottom: 1px solid rgb(var(--c-divider));
}

.hs-check dt {
  display: flex;
  align-items: center;
  gap: 2.2cqw;
  margin: 0;
  font-weight: 600;
  font-size: max(12.5px, 3.7cqw);
  color: rgb(var(--c-ink));
}

.hs-check dd {
  margin: 1.4cqw 0 0 5.4cqw;
  font-size: max(11.5px, 3.3cqw);
  line-height: 1.55;
  color: rgb(var(--c-slate-600));
}

.hs-check-state {
  margin-left: auto;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: max(9px, 2.5cqw);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.hs-dot {
  width: 2.2cqw;
  min-width: 7px;
  aspect-ratio: 1;
  border-radius: 50%;
  flex-shrink: 0;
}

.hs-dot-ok { background: rgb(var(--c-ok)); }
.hs-dot-degraded { background: rgb(var(--c-warn)); }
.hs-dot-down { background: rgb(var(--c-bad)); }

/* A leading number or time on a check row: the menu index on Platform, the
   clock on the Jua Kali timeline. Fixed width so the labels beside them line
   up down the column. */
.hs-num {
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-weight: 600;
  color: rgb(var(--c-signal-600));
  min-width: 4.2em;
  flex-shrink: 0;
}

.hs-check dt:has(.hs-num) { gap: 0; }

/* The price sits on the plan heading rather than under it, so the two read as
   one line at a glance. */
.hs-price {
  display: block;
  margin-top: 0.9cqw;
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: max(11px, 3.1cqw);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: rgb(var(--c-signal-600));
}

/* Two lines under one time on the Jua Kali timeline. */
.hs-check dd + dd { margin-top: 1.6cqw; }
.hs-check dd strong { color: rgb(var(--c-ink)); }

.hs-legal-body li { margin-top: 1.4cqw; }

.hs-legal-body a {
  color: rgb(var(--c-ink));
  text-decoration: underline;
  text-decoration-color: rgb(var(--c-divider));
  text-underline-offset: 2px;
}

.hs-legal-body a:not(.btn):hover { color: rgb(var(--c-signal-600)); }

/* ── One phone per page below the split ─────────────────────────────────────
   Two phones side by side stop working long before a tablet, so under 1024px
   the argument screen steps aside and the form takes the column.

   The frame stays at every width; only the count changes. Stripping it and
   letting the screen become the page makes the product look like one thing on a
   laptop and another on a handset, and takes the theme with it: a screen that is
   the page cannot also be a lit white device on a dark ground. */
/* One handset instead of two: the error pages and any other single-phone stage.
   The slot is the full container so the device is sized the same way, then
   centred rather than pinned to a half. */
.hs-pair--single {
  grid-template-columns: 1fr;
  justify-items: center;
}

.hs-pair--single .hs--deck { --hs-slot: 100cqw; }

/* The error screen reads as one centred block: code, sentence, then actions. */
.hs-err { text-align: center; }
.hs-err h1 { text-wrap: balance; }

.hs-form .hs-err-code {
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
  font-size: max(34px, 15cqw);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.04em;
  /* signal-600 rather than the brand's signal-500: at this size the numeral is
     large text, which needs 3:1, and #FF6A00 on white sits just under it at 2.9.
     signal-600 reads as the same orange and clears the threshold. */
  color: #FF6A00;
  margin: 0 0 2cqw;
}

.hs-form .hs-err-actions {
  display: grid;
  gap: 2.6cqw;
  margin-top: 7cqw;
}

@media (max-width: 1023px) {
  .hs-pair { grid-template-columns: 1fr; }
  .hs-say-phone { display: none; }
  /* One column, so the phone gets the whole width rather than half of it. */
  .hs--deck { --hs-slot: 100cqw; }
}

/* Below this the phone is nearly as wide as the window, and the floating theme
   control — fixed to the top right corner — landed on top of the device. The
   band at the top is the control's own space; the phone sizes itself from what
   is left, so the two cannot meet. */
@media (max-width: 640px) {
  /* The control's own offset plus its 38px box plus a gap. A flat guess left a
     one-pixel corner touching at 360 and 320. */
  .hs-pair { padding-top: calc(clamp(10px, calc(var(--app-vh, 100vh) * 0.018), 22px) + 46px); }
}

/* On a narrow viewport a fixed-width frame takes the width it needs rather than
   the width the desktop layout asked for. The decks size themselves against the
   window already, so this is for the preset sizes only. */
@media (max-width: 480px) {
  .hs--sm, .hs--md, .hs--lg { --hs-w: 76vw; }
}

/* ── NO ZOOM ON FOCUS ───────────────────────────────────────────────────────
   iOS Safari zooms the page into any field whose text is smaller than 16px, and
   it does not zoom back out when the field is left. The fields on the glass are
   sized in cqw and land around 12px on a handset, so without a floor every tap
   into one magnifies the page and leaves it that way.

   Sixteen pixels on coarse pointers is the fix. The alternative — user-scalable=no
   in the viewport meta — also stops the zoom, by taking pinch-to-zoom away from
   everyone, which is a real accessibility loss for the sake of a layout bug.

   Scoped to coarse pointers so a narrow desktop window keeps the proportional
   scale; only touch devices, which are the only ones that do this, are changed. */
@media (pointer: coarse) {
  .input, .select, .textarea,
  .hs-form .input, .hs-form .select, .hs-form .textarea,
  .hs-form-fields .input, .hs-form-fields .select, .hs-form-fields .textarea,
  .hs-field, input.hs-dialed { font-size: 16px; }
}

/* Nothing may push the page sideways, at any width the browser will report. */
@media (max-width: 260px) {
  .brand-word { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .hs-key b, .hs-fab, .hs-act, .hs-field { transition: none; }
}
