/* Subtick - the app shell.
 *
 * One theme, everywhere in the backend: the home page, the control panel, the setup
 * diagnostics. It does not follow the overlay theme and never did anything useful by
 * doing so - the panel's job is to let you judge the overlay, and chrome that
 * repaints itself every time you click a thumbnail is chrome you end up judging
 * instead. The seven overlay themes live in public/themes/<id>.css and apply only to
 * the overlay and to the preview iframes inside this shell.
 *
 * The overlay is deliberately not styled from here: it ships its own inline CSS so
 * an OBS browser source never waits on a second request before painting.
 *
 * Light is the default and dark follows the system setting. Both are authored, not
 * derived: every pair of colours in both modes is asserted against WCAG AA by
 * test/app-theme.test.js, which parses this file.
 */

/* Archivo for anything that behaves like a title, Inter for everything that behaves
   like text, IBM Plex Mono for clocks, amounts, keys and code. Three families, one
   job each; nothing here is loaded from a CDN. */
/* Each face declares the range it is willing to answer for rather than a single
   weight. Four woff2 files cover every weight the app asks for, and nothing is ever
   synthesised: a browser asked for a 700 it has no file for smears the 600 outline
   sideways, which at 76px on the clock is visible as a smudge rather than as bold.
   The practical effect is that 600 and 700 are the same ink in Inter and in the
   mono, and the step up to a real bold happens in Archivo, which is where every
   title, button and label on the page is set. */
@font-face { font-family: "Archivo"; font-weight: 600 700; font-display: swap; src: url(/fonts/archivo-700.woff2) format("woff2"); }
@font-face { font-family: "Inter"; font-weight: 100 500; font-display: swap; src: url(/fonts/inter-400.woff2) format("woff2"); }
@font-face { font-family: "Inter"; font-weight: 600 900; font-display: swap; src: url(/fonts/inter-600.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-weight: 100 450; font-display: swap; src: url(/fonts/plexmono-400.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-weight: 451 900; font-display: swap; src: url(/fonts/plexmono-500.woff2) format("woff2"); }

:root {
  /* ---- Light: warm paper ----
     A bone page rather than a blue-grey one, white cards, warm hairlines, and a
     single deep teal that means "this is the action" and nothing else. The only
     saturated thing on a panel should be the overlay you are building. */
  --shell: #f5f4f1;
  --surface: #ffffff;
  /* Card headers carry a hair of the page colour, so a card reads as a labelled
     tray rather than as a white rectangle with a line across it. */
  --surface-head: #fbfaf8;
  --raise: #efeeea;
  --raise-2: #e5e3dd;
  /* Two hairlines, two jobs. --line rules between sections and around cards and
     stays quiet; --line-2 draws controls - an input, a select, a switch, a soft
     button on a white card - and therefore clears 3:1 as WCAG asks of non-text UI.
     A 1.5:1 border on a white field is a decoration, not an affordance. */
  --line: #e3e1da;
  --line-2: #8d8980;
  --line-hover: #56534c;
  --ink: #1a1a19;
  --ink-dim: #575650;
  --ink-faint: #6a6860;
  --brand: #0f6156;
  --brand-hi: #0b4a41;
  --brand-ink: #ffffff;
  --ok: #1d6a42;
  --warn: #87580f;
  --bad: #b2251d;
  --ok-ink: #ffffff;
  --warn-ink: #68450c;
  --bad-ink: #8c1911;
  --ok-soft: rgba(29, 106, 66, 0.09);
  --ok-line: rgba(29, 106, 66, 0.38);
  --warn-soft: rgba(135, 88, 15, 0.09);
  --warn-line: rgba(135, 88, 15, 0.38);
  --bad-soft: rgba(178, 37, 29, 0.08);
  --bad-line: rgba(178, 37, 29, 0.36);

  /* The clock deck is the one dark slab on the page: an instrument face the eye
     lands on first, and the part a moderator reads across a room. It is the same
     slab in both modes, which is why it carries its own three tokens. */
  --deck-bg: #1b1d1f;
  --deck-ink: #f4f4f2;
  --deck-dim: #a9a7a0;
  --deck-line: #34373a;

  --input-bg: #ffffff;
  --input-well: inset 0 1px 2px rgba(26, 24, 20, 0.05);
  --focus-ring: rgba(15, 97, 86, 0.26);
  --knob-on: #ffffff;
  --topbar-bg: #f5f4f1;
  --scrim: rgba(22, 21, 19, 0.44);
  /* Shadows are tinted to the page hue and layered: a contact shadow plus one soft
     cast. A pure-black drop on warm paper is the thing that reads as a template. */
  --shadow-1: 0 1px 1px rgba(26, 24, 20, 0.035), 0 2px 6px -3px rgba(26, 24, 20, 0.07);
  --shadow-2: 0 1px 2px rgba(26, 24, 20, 0.05), 0 16px 40px -12px rgba(26, 24, 20, 0.22);
  /* The transparency checkerboard around the overlay preview, and the flat backdrop
     the overlay thumbnails sit on. The thumbnails stay on a mid slate in both modes:
     six of the seven themes are dark-on-transparent and need something to sit on. */
  --check-a: #dedbd4;
  --check-b: #ecebe6;
  --mini-bg: #2b2e33;
  /* 1 while the shell is painting a light page. The panel reads it to tell the
     overlay preview which transparency checkerboard to draw inside its own iframe. */
  --app-light: 1;

  --font-ui: "Inter", ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --font-display: "Archivo", "Inter", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --display-track: -0.02em;
  --display-case: none;

  /* One radius system, concentric: a child never rounds more than its parent. */
  --r: 10px;
  --r-sm: 8px;
  --r-xs: 6px;
  --btn-radius: 8px;
  /* One ease everywhere. Decelerating, no overshoot: a bouncing UI reads as a toy,
     and this tool runs for days on someone's second monitor. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --t: 160ms;
  --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M6 8.5l4 4 4-4' fill='none' stroke='%23575650' stroke-width='1.9' stroke-linecap='round'/%3E%3C/svg%3E");
  color-scheme: light;
}

/* ---- Dark: the same room with the lights off ----
   Authored rather than inverted. The neutrals keep a trace of the same warmth so
   the two modes are recognisably one product, the teal is lifted until it clears AA
   as both text and a fill, and the deck slab goes a step darker than the page so it
   is still the thing you look at first. */
@media (prefers-color-scheme: dark) {
  :root {
    --shell: #15161a;
    --surface: #1c1e22;
    --surface-head: #202327;
    --raise: #262930;
    --raise-2: #2f333a;
    --line: #2b2e35;
    --line-2: #6e747e;
    --line-hover: #9095a0;
    --ink: #ecebe7;
    --ink-dim: #a9adb5;
    --ink-faint: #9095a0;
    --brand: #45b7a4;
    --brand-hi: #63cdba;
    --brand-ink: #04231f;
    --ok: #4cc085;
    --warn: #dda63f;
    --bad: #f0766f;
    --ok-ink: #04231a;
    --warn-ink: #f0c87e;
    --bad-ink: #f8b4ae;
    --ok-soft: rgba(76, 192, 133, 0.12);
    --ok-line: rgba(76, 192, 133, 0.36);
    --warn-soft: rgba(221, 166, 63, 0.12);
    --warn-line: rgba(221, 166, 63, 0.36);
    --bad-soft: rgba(240, 118, 111, 0.12);
    --bad-line: rgba(240, 118, 111, 0.36);

    --deck-bg: #0e1013;
    --deck-ink: #f1f1ef;
    --deck-dim: #9ea3ab;
    --deck-line: #31353d;

    --input-bg: #141619;
    --input-well: inset 0 1px 2px rgba(0, 0, 0, 0.3);
    --focus-ring: rgba(69, 183, 164, 0.3);
    --knob-on: #04231f;
    --topbar-bg: #15161a;
    --scrim: rgba(6, 7, 9, 0.66);
    --shadow-1: 0 1px 1px rgba(0, 0, 0, 0.3), 0 2px 6px -3px rgba(0, 0, 0, 0.4);
    --shadow-2: 0 1px 2px rgba(0, 0, 0, 0.4), 0 16px 40px -12px rgba(0, 0, 0, 0.6);
    --check-a: #23262c;
    --check-b: #1b1e23;
    --mini-bg: #23262b;
    --app-light: 0;
    --select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M6 8.5l4 4 4-4' fill='none' stroke='%23a9adb5' stroke-width='1.9' stroke-linecap='round'/%3E%3C/svg%3E");
    color-scheme: dark;
  }
}

/* ---- The dark slab ----
   The clock deck is one dark instrument face in the middle of a light page, in both
   modes. It holds buttons, number inputs, a select and three tiers of label, so it
   re-points the tokens rather than restyling the components: every control inside it
   is the same component as everywhere else, reading a different palette. Geometry
   stays with the panel; only the palette is here, because this is the file whose
   contrast is asserted.

   One inner palette serves both modes. Only the slab colour differs, and it differs
   downwards, so the dark mode slab is more contrasty than the light mode one rather
   than less. */
.deck {
  --surface: #2e3339;
  --surface-head: #2e3339;
  --raise: #272b30;
  --raise-2: #31363a;
  --line: #33373b;
  --line-2: #787e86;
  --line-hover: #a3a19a;
  --ink: #f4f4f2;
  --ink-dim: #b7b5ae;
  --ink-faint: #a3a19a;
  --brand: #4fc1ad;
  --brand-hi: #6ad3c0;
  --brand-ink: #04231f;
  --warn: #e9b659;
  --input-bg: #141618;
  --input-well: inset 0 1px 2px rgba(0, 0, 0, 0.34);
  --focus-ring: rgba(79, 193, 173, 0.32);
  --knob-on: #04231f;
  --shadow-1: none;
  color-scheme: dark;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html { background: var(--shell); }
body {
  margin: 0;
  min-height: 100dvh;
  background: var(--shell);
  color: var(--ink);
  font: 400 15px/1.55 var(--font-ui);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 {
  margin: 0; font-weight: 700; font-family: var(--font-display);
  letter-spacing: var(--display-track); text-transform: var(--display-case);
  text-wrap: balance;
}
p { margin: 0; text-wrap: pretty; }
a { color: var(--brand); text-underline-offset: 2px; }
input, select, button, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
/* Removes the 300ms double-tap-zoom delay on every control without disabling zoom. */
button, a, label, select, input[type="checkbox"], input[type="radio"] { touch-action: manipulation; }
::selection { background: var(--brand); color: var(--brand-ink); }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }
* { scrollbar-width: thin; scrollbar-color: var(--line-2) transparent; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* First focusable thing on the page, visible only once it has focus. */
.skip {
  position: fixed; top: 8px; left: 8px; z-index: 100; transform: translateY(-200%);
  padding: 9px 14px; border-radius: var(--r-sm); background: var(--surface);
  border: 1px solid var(--line-2); box-shadow: var(--shadow-2);
  font-size: 14px; font-weight: 600; text-decoration: none; color: var(--ink);
}
.skip:focus-visible { transform: none; }

/* ---------- Wordmark ----------
   "subtick" set tight and lowercase, the i picked out in the accent, beside a clock
   face cut open at the top right. The only brand ornament in the app. */
/* min-height, not height: the wordmark is a link and therefore a tap target, and
   on a phone a 30px one is under the 44px minimum. */
.mark { display: inline-flex; align-items: center; gap: 9px; min-height: 44px; text-decoration: none; color: var(--ink); }
.mark-glyph { width: 30px; height: 30px; flex: none; }
/* One rule per role rather than a literal per stroke, so the mark follows the
   palette instead of staying whatever colour it was authored in. */
.mark-glyph .g-ring { stroke: var(--line-2); }
.mark-glyph .g-brand { stroke: var(--brand); }
.mark-glyph .g-ink { stroke: currentColor; }
.mark-glyph .g-tick { stroke: var(--brand); }
.mark-word {
  font-family: var(--font-display);
  font-weight: 700; font-size: 20px; letter-spacing: -0.045em; line-height: 1;
}
.mark-word i { font-style: normal; color: var(--brand); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 38px; padding: 0 15px; border-radius: var(--btn-radius);
  border: 1px solid transparent; background: var(--raise); color: var(--ink);
  /* Several buttons are real <a href> elements - sign-in, Home - so they inherit the
     link underline unless it is turned off here. */
  text-decoration: none;
  font-family: var(--font-display); font-weight: 700; font-size: 13.5px;
  letter-spacing: -0.005em; white-space: nowrap;
  transition: background-color var(--t) var(--ease), border-color var(--t) var(--ease),
    color var(--t) var(--ease), transform 90ms var(--ease), opacity var(--t) var(--ease);
}
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn-primary { background: var(--brand); color: var(--brand-ink); border-color: var(--brand); }
.btn-primary:hover:not(:disabled) { background: var(--brand-hi); border-color: var(--brand-hi); }
.btn-soft { background: var(--surface); border-color: var(--line-2); box-shadow: var(--shadow-1); }
.btn-soft:hover:not(:disabled) { background: var(--raise); border-color: var(--line-hover); }
.btn-ghost { background: transparent; border-color: var(--line-2); }
.btn-ghost:hover:not(:disabled) { background: var(--raise); border-color: var(--line-hover); }
.btn-bare { background: transparent; border-color: transparent; color: var(--ink-dim); }
.btn-bare:hover:not(:disabled) { background: var(--raise); color: var(--ink); }
.btn-danger { background: transparent; border-color: var(--line-2); color: var(--bad); }
.btn-danger:hover:not(:disabled) { background: var(--bad-soft); border-color: var(--bad); }
.btn-sm { height: 32px; padding: 0 11px; font-size: 13px; border-radius: var(--r-xs); }
.btn-lg { height: 46px; padding: 0 22px; font-size: 15.5px; }
.btn .i { width: 17px; height: 17px; }

.i { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* ---------- Inputs ---------- */
.inp, select.inp {
  height: 38px; width: 100%; padding: 0 11px; border-radius: var(--r-sm);
  border: 1px solid var(--line-2); background: var(--input-bg); color: var(--ink);
  /* A hair of inset shadow reads as a well to put something in. */
  box-shadow: var(--input-well);
  transition: border-color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.inp::placeholder { color: var(--ink-faint); }
.inp:hover { border-color: var(--line-hover); }
/* A 1px border recolour is not a focus indicator anyone can find on a form. The
   ring is the same shape the global :focus-visible rule draws, so a keyboard user
   sees one consistent treatment whatever they land on. */
.inp:focus-visible, .inp:focus-within {
  outline: none; border-color: var(--brand);
  box-shadow: var(--input-well), 0 0 0 3px var(--focus-ring);
}
/* A colour swatch is a button in all but name; it needs the same ring. */
input[type="color"].inp:focus-visible { box-shadow: 0 0 0 3px var(--focus-ring); }
input[type="range"] { accent-color: var(--brand); }
input[type="range"]:focus-visible { outline: 2px solid var(--brand); outline-offset: 4px; }
select.inp {
  appearance: none; padding-right: 32px; cursor: pointer;
  background: var(--input-bg) var(--select-arrow) right 9px center / 15px no-repeat;
  /* A clipped option used to end mid-word ("...and stop adding t"). If a wider
     typeface ever overruns a control again it ends in an ellipsis, which at least
     reads as "there is more" rather than as a typo. */
  text-overflow: ellipsis;
}
/* Size from the content rather than from a px literal. A hand-measured width on a
   <select> is what clips its longest option, and the phone breakpoint's 16px type
   makes every such measurement wrong by about a tenth. */
/* `select.inp` sets width:100%, so this has to match on the element too or the
   control stretches across its row instead of hugging its longest option. */
select.inp-auto, .inp-auto { width: auto; max-width: 100%; }
.inp-num { text-align: right; font-variant-numeric: tabular-nums; min-width: 72px; }
input[type="color"].inp { padding: 3px; height: 34px; cursor: pointer; box-shadow: none; }

/* Switch */
.sw { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; user-select: none; }
.sw input { position: absolute; opacity: 0; width: 0; height: 0; }
.sw-track {
  width: 38px; height: 22px; border-radius: 999px; background: var(--raise-2);
  border: 1px solid var(--line-2); position: relative; flex: none;
  transition: background-color var(--t) var(--ease), border-color var(--t) var(--ease);
}
.sw-track::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
  background: var(--ink-faint); transition: transform var(--t) var(--ease), background-color var(--t) var(--ease);
}
.sw input:checked + .sw-track { background: var(--brand); border-color: var(--brand); }
.sw input:checked + .sw-track::after { transform: translateX(16px); background: var(--knob-on); }
.sw input:focus-visible + .sw-track { outline: 2px solid var(--brand); outline-offset: 2px; }
.sw-label { font-size: 14px; }

/* ---------- Structure ---------- */
.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  height: 60px; padding: 0 20px;
  background: var(--topbar-bg); box-shadow: 0 1px 0 var(--line);
  position: sticky; top: 0; z-index: 20;
}
.topbar-actions { display: flex; align-items: center; gap: 8px; }

.card {
  border: 1px solid var(--line); border-radius: var(--r); background: var(--surface);
  box-shadow: var(--shadow-1);
}
.card-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--line);
  background: var(--surface-head);
  border-radius: calc(var(--r) - 1px) calc(var(--r) - 1px) 0 0;
}
.card-head h2 { font-size: 14.5px; }
.card-body { padding: 16px; }

.eyebrow { font-size: 11px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-faint); }
.hint { font-size: 13px; color: var(--ink-dim); line-height: 1.5; max-width: 68ch; }
.hint.bad { color: var(--bad-ink); }
.grid { display: grid; gap: 12px; }
.grid.two { grid-template-columns: 1fr 1fr; }
.grid.three { grid-template-columns: repeat(3, 1fr); }
.grid.four { grid-template-columns: repeat(4, 1fr); }
.row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.row.tight { gap: 6px; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.field { display: grid; gap: 6px; min-width: 0; }
.field > label { font-size: 13px; color: var(--ink-dim); font-weight: 400; }
.stack { display: grid; gap: 16px; }

.pill {
  display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px;
  border-radius: 999px; background: var(--raise); border: 1px solid var(--line-2);
  font-size: 12px; font-weight: 600; color: var(--ink-dim);
}
.pill.on { background: var(--ok-soft); border-color: var(--ok-line); color: var(--ok); }
.pill.off { background: var(--warn-soft); border-color: var(--warn-line); color: var(--warn); }
.pill.live::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

.code {
  font-family: var(--font-mono); font-size: 12.5px;
  background: var(--input-bg); border: 1px solid var(--line); border-radius: var(--r-xs);
  padding: 9px 11px; color: var(--ink-dim); overflow-x: auto; white-space: pre; margin: 0;
}

/* Toast strip for save state and errors. */
.toasts {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: 60;
  display: grid; gap: 8px; justify-items: center; pointer-events: none;
  max-width: min(94vw, 560px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.toast {
  display: inline-flex; align-items: center; gap: 12px; max-width: 100%;
  padding: 10px 16px; border-radius: var(--r-sm); background: var(--surface);
  border: 1px solid var(--line-2); color: var(--ink);
  font-size: 14px; font-weight: 600; box-shadow: var(--shadow-2);
  animation: toast-in 240ms var(--ease) both;
}
/* A toast that carried an Undo button used to be unclickable: the strip turns
   pointer events off so it never blocks the panel underneath, and nothing turned
   them back on for the one child that needs them. */
.toast:has(.toast-action) { pointer-events: auto; }
.toast.leaving { animation: toast-out 180ms var(--ease) both; }
.toast.bad { border-color: var(--bad-line); color: var(--bad-ink); }
.toast.ok { border-color: var(--ok-line); color: var(--ok); }
.toast-text { overflow: hidden; text-overflow: ellipsis; }
.toast-action {
  flex: none; height: 28px; padding: 0 12px; border-radius: var(--r-xs);
  border: 1px solid var(--line-2); background: var(--raise); color: var(--ink);
  font-size: 13px; font-weight: 700;
}
.toast-action:hover { background: var(--raise-2); border-color: var(--line-hover); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(6px); } }

/* ---------- Confirm dialog ----------
   Destructive actions used to call window.confirm(), which cannot be styled, reads
   as a browser security prompt rather than part of the app, and on a phone covers
   the thing it is asking about. This is the same question in the product's voice,
   with the destructive choice never the one that has focus. */
.modal-back {
  position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: 20px;
  background: var(--scrim); overscroll-behavior: contain;
  animation: fade-in 120ms var(--ease) both;
}
.modal {
  width: min(460px, 100%); border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--surface); box-shadow: var(--shadow-2);
  padding: 20px; display: grid; gap: 12px;
  animation: modal-in 160ms var(--ease) both;
}
.modal h2 { font-size: 17px; }
/* A dialog body is sometimes a short list, one line per item. */
.modal .hint { white-space: pre-line; }
.modal .row { justify-content: flex-end; margin-top: 4px; }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-in { from { opacity: 0; transform: translateY(10px) scale(0.985); } to { opacity: 1; transform: none; } }

/* ---------- Narrow screens ----------
   A moderator running the clock from a phone is a first-class case: the quick-add
   buttons and Pause are what they came for, and nothing may need a horizontal
   scroll to reach. */
@media (max-width: 680px) {
  .topbar { height: auto; min-height: 56px; padding: 8px 12px; flex-wrap: wrap; row-gap: 8px; }
  .topbar-actions { width: 100%; overflow-x: auto; justify-content: flex-start; padding-bottom: 2px; }
  .grid.two, .grid.three, .grid.four { grid-template-columns: 1fr; }
  .card-body { padding: 13px; }
  .card-head { padding: 11px 13px; }
  /* 44px is the smallest comfortable touch target; a 32px btn-sm is not one. */
  .btn { height: 44px; padding: 0 16px; }
  /* 44px is the smallest comfortable touch target, and a "small" button on a phone
     is still something a thumb has to hit. The size difference survives as padding. */
  .btn-sm { height: 44px; padding: 0 13px; }
  .btn-lg { height: 48px; }
  .inp, select.inp { height: 44px; font-size: 16px; } /* 16px stops iOS zooming on focus */
  .toasts { left: 12px; right: 12px; bottom: 12px; transform: none; max-width: none; }
  .toast { width: 100%; justify-content: space-between; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; }
}
