/* Self-hosted variable fonts (SIL OFL 1.1, see web/fonts/LICENSE-*.txt). */

@font-face {
  font-family: "Geologica";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/static/fonts/geologica-cyrillic.woff2?v=fcc480fd5afe") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: "Geologica";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/static/fonts/geologica-latin-ext.woff2?v=fcc480fd5afe") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Geologica";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/static/fonts/geologica-latin.woff2?v=fcc480fd5afe") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Golos Text";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/static/fonts/golos-text-cyrillic.woff2?v=fcc480fd5afe") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: "Golos Text";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/static/fonts/golos-text-latin-ext.woff2?v=fcc480fd5afe") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Golos Text";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/static/fonts/golos-text-latin.woff2?v=fcc480fd5afe") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Inter: the admin's typeface. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/static/fonts/inter-cyrillic.woff2?v=fcc480fd5afe") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/static/fonts/inter-latin-ext.woff2?v=fcc480fd5afe") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/static/fonts/inter-latin.woff2?v=fcc480fd5afe") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/*
 * Design tokens, "Precision".
 * Four primitives come from /theme.css (editable in the admin): --accent-base, --ink-base,
 * --paper-base and --radius-base. Every color, neutral and radius below derives from them, for
 * the light and the dark theme alike. Components never use literal colors, sizes or durations.
 */
:root {
  --accent-base: #1f4fe0;
  --ink-base: #111214;
  --paper-base: #fbfbfa;
  --radius-base: 12px;

  color-scheme: light dark;

  /* Neutrals: light mixes ink into paper, dark mixes paper into ink. */
  --bg: light-dark(var(--paper-base), color-mix(in oklab, var(--ink-base) 85%, black));
  --surface: light-dark(#ffffff, color-mix(in oklab, var(--ink-base) 97.5%, var(--paper-base)));
  --chrome: light-dark(color-mix(in oklab, var(--ink-base) 3%, var(--paper-base)), color-mix(in oklab, var(--ink-base) 94.5%, var(--paper-base)));
  --chrome-2: light-dark(color-mix(in oklab, var(--ink-base) 6%, var(--paper-base)), color-mix(in oklab, var(--ink-base) 91%, var(--paper-base)));
  --ink: light-dark(var(--ink-base), color-mix(in oklab, var(--paper-base) 96.5%, var(--ink-base)));
  --ink-2: light-dark(color-mix(in oklab, var(--ink-base) 72%, var(--paper-base)), color-mix(in oklab, var(--paper-base) 65%, var(--ink-base)));
  /* ink-3 is the quietest text; it still reads at 4.5:1 on every background (tests/tokens_contrast.rs). */
  --ink-3: light-dark(color-mix(in oklab, var(--ink-base) 61%, var(--paper-base)), color-mix(in oklab, var(--paper-base) 58%, var(--ink-base)));
  --line: light-dark(color-mix(in oklab, var(--ink-base) 9%, var(--paper-base)), color-mix(in oklab, var(--ink-base) 90%, var(--paper-base)));
  --line-strong: light-dark(color-mix(in oklab, var(--ink-base) 19%, var(--paper-base)), color-mix(in oklab, var(--ink-base) 80%, var(--paper-base)));
  /* A field's fill barely differs from the page, so its border is what shows where it is: 3:1 (palette.rs). */
  --field-line: light-dark(color-mix(in oklab, var(--ink-base) 45%, var(--paper-base)), color-mix(in oklab, var(--ink-base) 53%, var(--paper-base)));
  --inverse: var(--ink);
  --on-inverse: var(--bg);
  /* WebKit (Safari) crashes the page on a color-mix() whose two colors are both color-mix(), and in the dark theme
     --bg and --ink are. So the shades mixed from the two are written out there, for the default primitives: the
     band's quieter texts (--on-inverse 72% and 55% into --inverse) and a dark button under the pointer (--ink 86%
     into --bg). */
  --on-inverse-2: light-dark(color-mix(in srgb, var(--paper-base) 72%, var(--ink-base)), #4c4c4d);
  --on-inverse-3: light-dark(color-mix(in srgb, var(--paper-base) 55%, var(--ink-base)), #737374);
  --ink-hover: light-dark(color-mix(in oklab, var(--ink-base) 86%, var(--paper-base)), #cccdcc);

  /* Accent: the dark theme lifts lightness and keeps the hue. */
  --accent-dark: color-mix(in srgb, var(--accent-base) 62%, white);
  --accent: light-dark(var(--accent-base), var(--accent-dark));
  --accent-hover: light-dark(color-mix(in srgb, var(--accent-base) 82%, black), color-mix(in srgb, var(--accent-dark) 85%, white));
  /* Dark: --accent 15% into --surface, its ink and paper mixed in one at a time, so that no color-mix() gets two
     color-mix() colors (see --on-inverse-2): --accent is one where the browser lacks relative colors. */
  --accent-soft: light-dark(color-mix(in oklab, var(--accent) 9%, var(--surface)), color-mix(in oklab, color-mix(in oklab, var(--accent) 15.3257%, var(--ink-base)) 97.875%, var(--paper-base)));
  --accent-ink: light-dark(var(--accent-base), var(--accent-dark));
  --on-accent: light-dark(#ffffff, color-mix(in oklab, var(--ink-base) 85%, black));
  --ring-color: light-dark(color-mix(in srgb, var(--accent) 16%, transparent), color-mix(in srgb, var(--accent) 30%, transparent));
  --ring: 0 0 0 4px var(--ring-color);

  /* Status colors stay fixed: they mean something regardless of the brand. */
  --success: light-dark(#2b7146, #6cc28e);
  --warning: light-dark(#8c5a0b, #e0a54a);
  --danger: light-dark(#c0362c, #f07a70);
  --info: var(--accent);
  /* What the assistant made by itself, such as a folder of chats. */
  --ai: light-dark(#6b3fc4, #b89cff);
  --success-soft: light-dark(color-mix(in oklab, var(--success) 10%, var(--surface)), color-mix(in oklab, var(--success) 16%, var(--surface)));
  --warning-soft: light-dark(color-mix(in oklab, var(--warning) 11%, var(--surface)), color-mix(in oklab, var(--warning) 16%, var(--surface)));
  --danger-soft: light-dark(color-mix(in oklab, var(--danger) 9%, var(--surface)), color-mix(in oklab, var(--danger) 16%, var(--surface)));
  --info-soft: var(--accent-soft);
  --on-danger: light-dark(#ffffff, #111214);
  /* Fixed in both themes: a switch knob stays white, a device frame stays near-black. */
  --knob: #ffffff;
  --device: #111214;
  --device-edge: rgb(255 255 255 / 0.12);

  /* Type */
  --font-display: "Geologica", "Golos Text", system-ui, sans-serif;
  --font-body: "Golos Text", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-system: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;

  --fs-2xs: 0.75rem;
  --fs-xs: 0.8125rem;
  --fs-sm: 0.875rem;
  --fs-md: 1rem;
  --fs-lg: 1.125rem;
  --fs-xl: 1.25rem;
  --fs-2xl: clamp(1.5rem, 1.25rem + 1vw, 2rem);
  --fs-3xl: clamp(2rem, 1.45rem + 2.2vw, 2.75rem);
  --fs-4xl: clamp(2.5rem, 1.25rem + 5vw, 4.5rem);
  --lh-display: 1.02;
  --lh-tight: 1.08;
  --lh-snug: 1.3;
  --lh-body: 1.6;
  --tracking-display: -0.045em;
  --tracking-title: -0.03em;
  --tracking-snug: -0.015em;
  --tracking-caps: 0.08em;
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  /* Space: a 4px grid */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.25rem;
  --s-6: 1.5rem;
  --s-7: 2rem;
  --s-8: 2.5rem;
  --s-9: 3rem;
  --s-10: 4rem;
  --s-11: 5rem;
  --s-12: 6rem;
  --s-13: 8rem;
  --s-14: 9rem;
  --section-y: clamp(4rem, 2.4rem + 6.4vw, 9rem);

  /* Shape */
  --control-h: 3rem;
  --control-h-sm: 2.5rem;
  --r-xs: calc(var(--radius-base) / 3);
  --r-sm: calc(var(--radius-base) * 2 / 3);
  --r-md: var(--radius-base);
  --r-lg: calc(var(--radius-base) * 5 / 3);
  --r-xl: calc(var(--radius-base) * 7 / 3);
  --r-pill: 999px;

  /* The one long shadow, for raised things and showcase frames only. */
  --shadow: 0 40px 80px -40px light-dark(rgb(17 18 20 / 0.35), rgb(0 0 0 / 0.8));
  --shadow-knob: 0 1px 2px light-dark(rgb(17 18 20 / 0.24), rgb(0 0 0 / 0.5));
  /* A selected thing lifted off its rail: the admin's active area. */
  --lift: 0 1px 2px light-dark(rgb(17 18 20 / 0.06), rgb(0 0 0 / 0.4)), 0 8px 24px -8px light-dark(rgb(17 18 20 / 0.14), rgb(0 0 0 / 0.6));

  /* Motion */
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-1: 150ms;
  --dur-2: 200ms;
  --dur-3: 260ms;

  /* Layout */
  --container: 1200px;
  --container-wide: 1360px;
  --container-narrow: 760px;
  --gutter: max(16px, min(4vw, 40px));
  --header-h: 64px;
  /* The cabinet's bottom bar on phones, without the safe area under it. */
  --cab-nav-h: 56px;
  /* The way the line runs: 1 left to right, -1 right to left. A move along the line is multiplied by it. */
  --dir: 1;

  --z-header: 50;
  --z-banner: 60;
  --z-overlay: 80;
  --z-toast: 90;

  --icon-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8.4l2.6 2.6L12 5.4' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --icon-calendar: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 3v3M17 3v3M4 9h16M6 5h12a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2z' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

[dir="rtl"] {
  --dir: -1;
}

[dir="ltr"] {
  --dir: 1;
}

@supports (color: oklch(from red l c h)) {
  :root {
    --accent-dark: oklch(from var(--accent-base) calc(l + 0.16) calc(c * 0.86) calc(h + 4));
  }
}

:root[data-theme="light"] {
  color-scheme: light;
}

:root[data-theme="dark"] {
  color-scheme: dark;
}

/* The admin's fixed palette, the same whatever the site's theme; admin.css builds the rest of its
   tokens on these. Only admin pages have body.admin. */
body.admin {
  --bg: light-dark(#ffffff, #18191b);
  --chrome: light-dark(#efefef, #242528);
  --chrome-2: light-dark(#e2e2e2, #2e2f33);
  --line: light-dark(#e9e9e9, #2a2b2e);
  --line-strong: light-dark(#e2e2e2, #37393d);
  --ink: light-dark(#111111, #ececed);
  --ink-2: light-dark(#5f5f5f, #8a8c91);
  --ink-3: light-dark(#8e8e8e, #62646a);
  /* The side menu: white like the page in the light theme, a step lighter than it in the dark one. */
  --nav-bg: light-dark(#ffffff, #1f2023);
  --dot-muted: light-dark(#bdbdbd, #3f4146);
  --accent: light-dark(#e60023, #d9213a);
  --accent-hover: light-dark(#ad081b, #b01a2f);
  --on-accent: #ffffff;
  --danger: light-dark(#c0362c, #ff8c99);
  --scrim: light-dark(color-mix(in srgb, var(--ink-base) 40%, transparent), rgb(0 0 0 / 0.6));
  /* The built-in mark on the sign-in screens (admin/guest_brand.html): its tile and its lines. */
  --logo: light-dark(#111214, #ececed);
  --logo-on: light-dark(#fbfbfa, #18191b);
}

/* The theme sample in the admin settings shows the site's colours: the tokens with a fixed white,
   built as above; admin.css builds the rest. */
.theme-sample {
  --surface: light-dark(#ffffff, color-mix(in oklab, var(--ink-base) 97.5%, var(--paper-base)));
  --on-accent: light-dark(#ffffff, color-mix(in oklab, var(--ink-base) 85%, black));
}

/* The assistant settings' own shades, the approved mockup's; admin.css ("assistant settings", "Admin kit" and
   the menu's "Menu badges") uses them. */
.aset,
.aset-dlg,
.aset-bar,
.admin-main:has(.aset) .admin-topbar,
.admin-main:has(.kit),
.side,
.kit-pane,
.kit-pane-b {
  --aset-pn: light-dark(#f5f5f5, #1f2023);
  --aset-sf: light-dark(#efefef, #26272a);
  --aset-ln2: light-dark(#dcdcdc, #37393d);
  --aset-ok: light-dark(#1a7f45, #2e9e5b);
  --aset-warn: light-dark(#b25e00, #e0a040);
  --aset-erb: light-dark(#fff1f2, #2b181b);
  --aset-erl: light-dark(#f6c5cd, #552329);
  --aset-ert: light-dark(#b0001b, #ff8c99);
}

/* The analytics page's own shades, the approved mockup's («Analytics B» in admin.css): the calendar's four
   steps and the numbers on the dark ones, the donut's two data shades, the soft green and red behind a
   change, and the blue of a search engine's letter. */
.kit.an {
  --an-h1: light-dark(#ececed, #26272a);
  --an-h2: light-dark(#cfd0d3, #3d3f44);
  --an-h3: light-dark(#6b6d73, #8f9197);
  --an-h4: light-dark(#2a2b2f, #e4e5e7);
  --an-on: light-dark(#ffffff, #111214);
  --an-data: light-dark(#2f3034, #d6d7da);
  --an-data2: light-dark(#b9babe, #5c5e64);
  --an-ok-soft: light-dark(#e7f4ec, #1c2a22);
  --an-bad-soft: light-dark(#fbeceb, #2b181b);
  --an-search: #4285f4;
}

/* The assistant's own shades, the approved mockup's («Assistant: «About the chat»» in admin.css): each tag's
   colour and its ground, and a photo's name, white over the dark shade at its foot whatever the theme. */
.chat-pane {
  --as-t-blue: light-dark(#1a56c4, #8fb4ff);
  --as-t-blue-b: light-dark(#e8f0fe, #1b2840);
  --as-t-amber: light-dark(#8a5300, #e8b65a);
  --as-t-amber-b: light-dark(#fcf0d9, #33280f);
  --as-t-violet: light-dark(#6b3fc4, #b89cff);
  --as-t-violet-b: light-dark(#f1eafe, #2a2140);
  --as-t-teal: light-dark(#126b55, #6fd1b2);
  --as-t-teal-b: light-dark(#e0f4ee, #14302a);
  --as-t-rose: light-dark(#b4232c, #ff8c99);
  --as-t-rose-b: light-dark(#fdeaea, #3a1a1d);
  --as-t-gray: light-dark(#5f5f5f, #a3a5aa);
  --as-t-gray-b: light-dark(#efefef, #2a2b2e);
  --as-ph-on: #ffffff;
  --as-ph-shade: rgb(0 0 0 / 55%);
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + var(--s-4));
}

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
  font-weight: var(--fw-regular);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

img,
svg,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-title);
  text-wrap: balance;
}

h3,
h4 {
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-snug);
}

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

a {
  color: inherit;
  text-decoration-color: color-mix(in oklab, currentColor 30%, transparent);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: color var(--dur-1) var(--ease), text-decoration-color var(--dur-1) var(--ease);
}

a:hover {
  text-decoration-color: currentColor;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

::selection {
  background: var(--ring-color);
  color: var(--ink);
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

fieldset {
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

fieldset > legend {
  margin-block-end: var(--s-2);
  padding: 0;
}

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: var(--s-7) 0;
}

table {
  font-variant-numeric: tabular-nums;
}

.sr-only,
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  inset-inline-start: var(--s-4);
  top: calc(-1 * var(--s-10));
  z-index: var(--z-toast);
  padding: var(--s-2) var(--s-4);
  background: var(--ink);
  color: var(--bg);
  border-radius: var(--r-pill);
}

.skip-link:focus {
  top: var(--s-3);
}

[hidden] {
  display: none !important;
}

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

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* Layout primitives */
.container {
  width: min(100% - max(var(--gutter), env(safe-area-inset-left)) - max(var(--gutter), env(safe-area-inset-right)), var(--container));
  margin-inline: auto;
}

.container-wide {
  width: min(100% - max(var(--gutter), env(safe-area-inset-left)) - max(var(--gutter), env(safe-area-inset-right)), var(--container-wide));
}

.container-narrow {
  width: min(100% - max(var(--gutter), env(safe-area-inset-left)) - max(var(--gutter), env(safe-area-inset-right)), var(--container-narrow));
}

.stack {
  display: grid;
  gap: var(--s-4);
  align-content: start;
}

/* A wide table inside scrolls in its own frame instead of stretching every card past the screen */
.stack > * {
  min-width: 0;
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: var(--s-4);
}

/* Text */
.display {
  font-family: var(--font-display);
  font-size: var(--fs-4xl);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
}

.eyebrow {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
}

.lead {
  color: var(--ink-2);
  font-size: var(--fs-lg);
  line-height: 1.55;
  max-width: 38em;
}

.muted {
  color: var(--ink-2);
}

/* The second thought of a headline: "Сайт, который продаёт. Каждый день." */
.thought {
  color: var(--ink-3);
}

.num,
.price {
  font-variant-numeric: tabular-nums;
}

.icon {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* In a right-to-left language the icons that point along the line point the other way. */
[dir="rtl"] .icon:has(use[href$="#arrow-left"], use[href$="#arrow-right"], use[href$="#arrow-up-right"], use[href$="#chevron-right"], use[href$="#external"], use[href$="#list"], use[href$="#send"], use[href$="#undo"], use[href$="#logout"]) {
  scale: -1 1;
}

/* Buttons: pills, 48px and 40px. One primary per screen. */
.btn {
  --btn-h: var(--control-h);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: var(--btn-h);
  padding: 0 var(--s-6);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--fs-md);
  font-weight: var(--fw-medium);
  line-height: 1.2;
  letter-spacing: -0.005em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background-color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease);
}

.btn:hover {
  border-color: var(--ink-3);
}

.btn:active {
  transform: scale(0.98);
}

.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.45;
  pointer-events: none;
}

.btn .icon {
  width: 1.125rem;
  height: 1.125rem;
}

.btn-primary {
  border-color: transparent;
  background: var(--accent);
  color: var(--on-accent);
}

.btn-primary:hover {
  border-color: transparent;
  background: var(--accent-hover);
}

.btn-ink {
  border-color: transparent;
  background: var(--ink);
  color: var(--bg);
}

.btn-ink:hover {
  border-color: transparent;
  background: var(--ink-hover);
}

.btn-ghost {
  border-color: transparent;
  background: transparent;
}

.btn-ghost:hover {
  border-color: transparent;
  background: var(--chrome);
}

.btn-danger {
  border-color: color-mix(in oklab, var(--danger) 35%, var(--line));
  color: var(--danger);
}

.btn-danger:hover {
  border-color: var(--danger);
  background: var(--danger-soft);
}

/* Delete in a row or a save bar (ui::confirm_delete): red words without a frame until hovered. */
.btn-danger-quiet {
  border-color: transparent;
  background: transparent;
  color: var(--danger);
}

.btn-danger-quiet:hover {
  border-color: transparent;
  background: var(--danger-soft);
}

.btn-danger-quiet:focus-visible {
  outline-color: var(--danger);
}

/* ui::confirm_delete without JavaScript: the button opens the question with the real Delete.
   .ask-box is the same question in place with or without JavaScript (retry a failed letter). */
.confirm-delete,
.ask-box {
  display: inline-block;
}

.confirm-delete > summary,
.ask-box > summary {
  list-style: none;
}

.confirm-delete > summary::-webkit-details-marker,
.ask-box > summary::-webkit-details-marker {
  display: none;
}

.confirm-delete-ask {
  display: grid;
  justify-items: start;
  gap: var(--s-2);
  margin-top: var(--s-2);
}

.btn-link {
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: var(--r-xs);
  background: none;
  color: var(--accent-ink);
}

.btn-link:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.btn-link .icon,
.more-link .icon {
  transition: translate var(--dur-2) var(--ease);
}

.btn-link:hover .icon,
.more-link:hover .icon {
  translate: calc(3px * var(--dir));
}

.btn-sm {
  --btn-h: var(--control-h-sm);
  padding: 0 var(--s-4);
  font-size: var(--fs-sm);
}

.btn-icon {
  width: var(--btn-h);
  padding: 0;
}

.btn.is-busy {
  cursor: progress;
  opacity: 0.7;
}

.more-link {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  color: var(--accent-ink);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-decoration: none;
}

.link-button {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: underline;
  text-decoration-color: color-mix(in oklab, currentColor 30%, transparent);
  text-underline-offset: 0.2em;
  cursor: pointer;
}

/* Fields: 48px like buttons, so rows align to the pixel. */
.field {
  display: grid;
  gap: var(--s-2);
  align-content: start;
}

.field-label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--ink);
}

.field-optional {
  margin-inline-start: var(--s-1);
  color: var(--ink-2);
  font-weight: var(--fw-regular);
}

.field-hint {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--fs-xs);
}

/* ui::checkbox and ui::radio: the box before its label, the whole row clickable. */
.check {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  font-size: var(--fs-sm);
  cursor: pointer;
}

/* The box sits on the middle of the label's first line, however many lines the label wraps to. */
.check > .checkbox,
.check > .radio {
  margin-block-start: calc((1lh - 1.25rem) / 2);
}

.os-apple .check > .checkbox,
.os-apple .check > .radio {
  margin-block-start: calc((1lh - 1.125rem) / 2);
}

@media (pointer: coarse) {
  .check {
    padding-block: calc((2.75rem - 1lh) / 2);
  }

  .check-group-items {
    gap: 0;
  }
}

/* The label of a checkbox, radio or switch, with its hint on the line below. */
.check-text {
  display: grid;
  gap: var(--s-1);
  min-width: 0;
  overflow-wrap: anywhere;
}

.check-text small {
  color: var(--ink-2);
  font-size: var(--fs-xs);
}

/* ui::check_group: a legend over its checkboxes, one per line or side by side. */
.check-group > legend {
  margin-bottom: 0;
}

.check-group-items {
  display: grid;
  gap: var(--s-2);
}

.check-group-inline .check-group-items {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
}

.field-error {
  display: flex;
  gap: var(--s-2);
  margin: 0;
  color: var(--danger);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
}

.input,
.select,
.textarea {
  width: 100%;
  min-height: var(--control-h);
  padding: 0 var(--s-4);
  border: 1px solid var(--field-line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--fs-md);
  line-height: 1.4;
  transition: border-color var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}

.textarea {
  min-height: 8rem;
  padding: var(--s-3) var(--s-4);
  resize: vertical;
  line-height: var(--lh-body);
}

/* What is typed keeps its own direction on a right to left page: a Russian company name keeps its
   quotes in place. A phone or an email always reads left to right. */
.input,
.textarea {
  unicode-bidi: plaintext;
}

input:is([type="tel"], [type="email"]) {
  direction: ltr;
}

.select {
  padding-inline-end: var(--s-10);
  appearance: none;
  background-image: var(--icon-chevron-tinted);
  background-repeat: no-repeat;
  background-position: right var(--s-4) center;
  background-size: 1rem;
  cursor: pointer;
  --icon-chevron-tinted: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%237c7e84' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
[dir="rtl"] .select {
  background-position: left var(--s-4) center;
}

/* The select controls.js draws on Windows, Linux and Android: the field is a combobox, the
   options open in a listbox kept inside the screen and its safe areas. */
.select-native {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

div.select {
  position: relative;
  display: flex;
  align-items: center;
  background-image: none;
  user-select: none;
}

div.select > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

div.select::after {
  content: "";
  position: absolute;
  top: 50%;
  inset-inline-end: var(--s-4);
  width: 1rem;
  height: 1rem;
  background: var(--ink-3);
  mask: var(--icon-chevron) center / contain no-repeat;
  translate: 0 -50%;
  transition: rotate var(--dur-1) var(--ease);
}

div.select[aria-expanded="true"] {
  border-color: var(--ink);
  box-shadow: var(--ring);
}

div.select[aria-expanded="true"]::after {
  rotate: 180deg;
}

div.select[aria-disabled] {
  background: var(--chrome);
  color: var(--ink-2);
  cursor: not-allowed;
}

.listbox {
  position: fixed;
  inset: auto;
  z-index: var(--z-overlay);
  max-width: calc(100vw - 2 * var(--s-2) - env(safe-area-inset-left) - env(safe-area-inset-right));
  max-height: min(20rem, calc(var(--listbox-room) - env(safe-area-inset-bottom)));
  margin: 0;
  padding: var(--s-1);
  overflow-y: auto;
  overscroll-behavior: contain;
  list-style: none;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow);
  font-size: var(--fs-md);
  animation: rise var(--dur-2) var(--ease-out);
}

.listbox.is-up {
  max-height: min(20rem, calc(var(--listbox-room) - env(safe-area-inset-top)));
}

.listbox [role="option"] {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: var(--control-h-sm);
  padding: 0 var(--s-3);
  border-radius: var(--r-sm);
  cursor: pointer;
}

.listbox .is-active {
  background: var(--chrome);
}

.listbox [aria-selected="true"] {
  font-weight: var(--fw-semibold);
}

.listbox [aria-selected="true"]::after {
  content: "";
  flex: none;
  width: 0.875rem;
  height: 0.875rem;
  background: var(--ink);
  mask: var(--icon-check) center / contain no-repeat;
}

.listbox [aria-disabled="true"] {
  color: var(--ink-3);
  cursor: default;
}

@media (pointer: coarse) {
  .listbox [role="option"] {
    min-height: 44px;
  }
}

.input:hover,
.select:hover,
.textarea:hover {
  border-color: var(--ink-3);
}

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: var(--ring);
}

/* The browser's own autofill tint ignores the palette and, in some browsers, the dark theme. */
.input:autofill,
.textarea:autofill {
  box-shadow: inset 0 0 0 100vmax var(--accent-soft);
  -webkit-text-fill-color: var(--ink);
  caret-color: var(--ink);
}
.input:autofill:focus,
.textarea:autofill:focus {
  box-shadow: var(--ring), inset 0 0 0 100vmax var(--accent-soft);
}

.input::placeholder,
.textarea::placeholder {
  color: var(--ink-3);
  opacity: 1;
}

.input[aria-invalid="true"],
.select[aria-invalid="true"],
.textarea[aria-invalid="true"],
.has-error .input,
.has-error .select,
.has-error .textarea {
  border-color: var(--danger);
}

.input[aria-invalid="true"]:focus,
.textarea[aria-invalid="true"]:focus,
.has-error .input:focus,
.has-error .textarea:focus {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--danger) 16%, transparent);
}

.input:disabled,
.select:disabled,
.textarea:disabled {
  background: var(--chrome);
  color: var(--ink-2);
  cursor: not-allowed;
}

/* A fixed prefix inside the field, e.g. +373 for Moldovan phones. */
.input-affix {
  display: flex;
  align-items: center;
  border: 1px solid var(--field-line);
  border-radius: var(--r-md);
  background: var(--surface);
  transition: border-color var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}

.input-affix > span {
  padding-inline-start: var(--s-4);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.input-affix > .input {
  min-height: calc(var(--control-h) - 2px);
  padding-inline-start: var(--s-2);
  border: 0;
  background: none;
  box-shadow: none;
  font-variant-numeric: tabular-nums;
}

.input-affix:hover {
  border-color: var(--ink-3);
}

.input-affix:focus-within {
  border-color: var(--ink);
  box-shadow: var(--ring);
}

.has-error .input-affix {
  border-color: var(--danger);
}

/* Dates and numbers off Apple systems: the calendar button takes the field's ink, a number gets
   − and + buttons from controls.js (the keyboard keeps the arrow keys). */
:root:not(.os-apple) .input:is([type="date"], [type="datetime-local"])::-webkit-calendar-picker-indicator {
  width: 1.25rem;
  height: 1.25rem;
  margin-inline-start: var(--s-2);
  padding: 0;
  background: var(--ink-3);
  mask: var(--icon-calendar) center / contain no-repeat;
  opacity: 1;
  cursor: pointer;
}

:root:not(.os-apple) .input:is([type="date"], [type="datetime-local"])::-webkit-calendar-picker-indicator:hover {
  background: var(--ink);
}

.input:is([type="date"], [type="datetime-local"], [type="number"]) {
  font-variant-numeric: tabular-nums;
}

.number-field > .input {
  min-width: 0;
  max-width: none;
  padding: 0 var(--s-1);
  text-align: center;
  appearance: textfield;
}

.number-field > .input::-webkit-inner-spin-button,
.number-field > .input::-webkit-outer-spin-button {
  margin: 0;
  appearance: none;
}

.number-field > button {
  flex: none;
  align-self: stretch;
  width: var(--control-h-sm);
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--r-md);
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-size: var(--fs-lg);
  line-height: 1;
  cursor: pointer;
}

.number-field > button:hover {
  background: var(--chrome);
  color: var(--ink);
}

.number-field:has(.input:disabled) {
  background: var(--chrome);
}

.number-field:has(.input:disabled) > button {
  color: var(--ink-3);
  cursor: not-allowed;
}

/* Files (ui::file_input): the site's own button in the page's language over a transparent native
   input, which takes the click, the drop and the keyboard; controls.js writes the chosen names. */
.file-field {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding-inline-start: var(--s-2);
  cursor: pointer;
}

.file-native {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.file-button {
  position: relative;
}

.file-button:has(.file-native:focus-visible) {
  box-shadow: var(--ring);
}

.file-field > .btn {
  flex: none;
  pointer-events: none;
}

.file-field:hover > .btn {
  border-color: var(--ink-3);
}

.file-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-field.is-empty > .file-name {
  color: var(--ink-2);
}

.file-field:focus-within {
  border-color: var(--ink);
  box-shadow: var(--ring);
}

.file-field:has([aria-invalid="true"]) {
  border-color: var(--danger);
}

.file-field:has(:disabled) {
  background: var(--chrome);
  cursor: not-allowed;
}

/* Colour: off Apple systems the swatch fills the control with the field's rounding. */
.input[type="color"] {
  width: var(--control-h);
  padding: var(--s-1);
  cursor: pointer;
}

:root:not(.os-apple) input[type="color"]::-webkit-color-swatch-wrapper {
  padding: 0;
}

:root:not(.os-apple) input[type="color"]::-webkit-color-swatch {
  border: 0;
  border-radius: var(--r-sm);
}

:root:not(.os-apple) input[type="color"]::-moz-color-swatch {
  border: 0;
  border-radius: var(--r-sm);
}

/* Checkbox, radio, switch: monochrome, ink when on. */
.checkbox,
.radio {
  flex: none;
  display: inline-grid;
  place-content: center;
  width: 1.25rem;
  height: 1.25rem;
  margin: 0;
  border: 1.5px solid var(--field-line);
  background: var(--surface);
  appearance: none;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}

.checkbox {
  border-radius: var(--r-xs);
}

.radio {
  border-radius: 50%;
}

.checkbox::before {
  content: "";
  width: 0.875rem;
  height: 0.875rem;
  background: var(--bg);
  mask: var(--icon-check) center / contain no-repeat;
  transform: scale(0);
  transition: transform var(--dur-1) var(--ease-out);
}

.checkbox:hover,
.radio:hover {
  border-color: var(--ink-3);
}

.checkbox:checked {
  border-color: var(--ink);
  background: var(--ink);
}

.checkbox:checked::before {
  transform: scale(1);
}

.radio:checked {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 4.5px var(--ink);
}

.checkbox:focus-visible,
.radio:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-color: var(--ink);
}

.has-error .checkbox {
  border-color: var(--danger);
}

/* Apple systems keep the native checkbox and radio, tinted with the accent. */
.os-apple .checkbox,
.os-apple .radio,
.os-apple .checkbox:checked,
.os-apple .radio:checked,
.os-apple .checkbox:focus-visible,
.os-apple .radio:focus-visible {
  width: 1.125rem;
  height: 1.125rem;
  border: 0;
  background: none;
  box-shadow: none;
  appearance: auto;
  accent-color: var(--accent);
}

.os-apple .checkbox::before {
  content: none;
}

.checkbox-row {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  cursor: pointer;
}

.checkbox-row .checkbox,
.checkbox-row .radio {
  margin-top: 0.1rem;
}

.switch {
  position: relative;
  display: inline-flex;
  flex: none;
}

.switch input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.switch span {
  width: 2.75rem;
  height: 1.625rem;
  padding: 3px;
  border-radius: var(--r-pill);
  background: var(--field-line);
  transition: background-color var(--dur-2) var(--ease);
}

.switch span::after {
  content: "";
  display: block;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: var(--knob);
  box-shadow: var(--shadow-knob);
  transition: translate var(--dur-2) var(--ease-out);
}

.switch input:checked + span {
  background: var(--ink);
}

.switch input:checked + span::after {
  translate: calc(1.125rem * var(--dir));
  background: var(--bg);
}

.switch input:disabled {
  cursor: not-allowed;
}

.switch input:disabled + span {
  opacity: 0.5;
}

.switch input:focus-visible + span {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Chips: tags, and as a checkbox group (<label class="chip-check"><input …><span>…</span></label>). */
.chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  min-height: 1.75rem;
  padding: 0 var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--ink-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
}

.chip-check {
  position: relative;
  display: inline-flex;
}

.chip-check input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.chip-check span {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-h-sm);
  padding: 0 var(--s-4);
  border: 1px solid var(--field-line);
  border-radius: var(--r-pill);
  background: var(--surface);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}

.chip-check span:hover {
  border-color: var(--ink-3);
}

.chip-check input:checked + span {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bg);
}

.chip-check input:focus-visible + span {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Phones get the 44px tap height even where the browser reports a fine pointer. */
@media (pointer: coarse), (max-width: 599px) {
  .chip-check span {
    min-height: 44px;
  }
}

/* Badges */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  min-height: 1.5rem;
  padding: 0 var(--s-2);
  border-radius: var(--r-pill);
  background: var(--chrome);
  color: var(--ink-2);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  line-height: 1;
  white-space: nowrap;
}

.badge::before {
  content: "";
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background: currentColor;
}

.badge-plain::before {
  content: none;
}

.badge-accent {
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.badge-ok {
  background: var(--success-soft);
  color: var(--success);
}

.badge-warn {
  background: var(--warning-soft);
  color: var(--warning);
}

.badge-danger {
  background: var(--danger-soft);
  color: var(--danger);
}

/* Files in a list: rows wrap and never run wider than their column. */
.file-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.file-list > li {
  min-width: 0;
  max-width: 100%;
}

/* A file in a list (cabinet/file_link.html): the icon on the left across both lines; the name on top, cut with an ellipsis; type and size below. */
.file-link {
  display: grid;
  min-height: 44px;
  max-width: 100%;
  grid-template-columns: auto auto minmax(0, 1fr);
  grid-template-areas:
    "icon name name"
    "icon type size";
  align-content: center;
  padding-block: var(--s-1);
  line-height: 1.3;
  text-decoration: none;
}

.file-link > .icon {
  grid-area: icon;
  align-self: center;
  width: 1.5rem;
  height: 1.5rem;
  margin-inline-end: var(--s-2);
}

.file-link > span {
  grid-area: name;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-decoration: underline 1px color-mix(in oklab, currentColor 30%, transparent);
}

.file-link:hover > span {
  text-decoration-color: currentColor;
}

.file-type {
  grid-area: type;
  margin-inline-end: 0.3em;
  color: var(--ink-2);
}

.file-link > .muted {
  grid-area: size;
  white-space: nowrap;
}

.file-type,
.file-link > .muted {
  font-size: var(--fs-xs);
}

/* Cards: a hairline and a 20px radius, never a shadow. */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-7);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}

/* ui::card: an icon and a heading on top, a link to the full list on the right. */
.card-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-width: 0;
}

.card-head > div:not(.card-actions) {
  flex: 1 1 14rem;
  min-width: 0;
}

.card-head h2 {
  font-size: var(--fs-lg);
  letter-spacing: var(--tracking-snug);
}

.card-head p {
  margin-top: var(--s-1);
  color: var(--ink-2);
  font-size: var(--fs-sm);
}

.card-head p:first-child {
  margin-top: 0;
}

.card-icon {
  display: grid;
  flex: none;
  align-self: flex-start;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--r-sm);
  background: var(--chrome);
  color: var(--ink-2);
}

/* Lists and tables run edge to edge; the head keeps its padding over a hairline. */
.card.card-flush {
  gap: 0;
  padding: 0;
}

.card-flush > .card-head {
  padding: var(--s-5) var(--s-6);
  border-bottom: 1px solid var(--line);
}

.card-narrow {
  max-width: 45rem;
}

/* ui::card_head: buttons on the right; a long one wraps instead of widening the card on a phone. */
.card-actions {
  display: flex;
  flex: none;
  flex-wrap: wrap;
  gap: var(--s-2);
  max-width: 100%;
}

.card-actions .btn {
  max-width: 100%;
  white-space: normal;
}

.card-flush .table-wrap {
  border: 0;
  border-radius: 0;
  background: none;
}

/* Name and value pairs are not a list: they keep the head's padding, as the sales «Today» card on the home page. */
.card-flush > .kv {
  padding: var(--s-5) var(--s-6);
}

.card-flush > .pager {
  padding: var(--s-3) var(--s-5);
  border-top: 1px solid var(--line);
}

.card-head + .module-row {
  border-top: 0;
}

/* ui::empty_state: what goes here and the first step, in the middle of its card. */
.empty {
  display: grid;
  justify-items: center;
  gap: var(--s-3);
  padding: var(--s-8) var(--s-6);
  text-align: center;
}

.empty-illo {
  display: grid;
  place-items: center;
  width: 4rem;
  height: 4rem;
  margin-bottom: var(--s-1);
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
}

.empty-illo :is(.icon, .sym) {
  width: 1.75rem;
  height: 1.75rem;
}

/* Illustrations: illo-inbox, illo-pages, illo-cases, illo-list, illo-files, illo-people,
   illo-search, illo-generic in img/icons.svg, drawn on 64×64. Shapes without their own fill take
   the soft accent. */
.empty-art {
  width: 6rem;
  height: 6rem;
  background: none;
  color: var(--ink-3);
}

.empty-art .icon {
  width: 100%;
  height: 100%;
  fill: var(--accent-soft);
  stroke-width: 1.8;
}

.empty :is(h2, h3) {
  font-size: var(--fs-lg);
  letter-spacing: var(--tracking-snug);
}

.empty p {
  max-width: 46ch;
  color: var(--ink-2);
}

.empty-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--s-2);
  margin-top: var(--s-2);
}

.empty-actions:empty {
  display: none;
}

/* ui::gate_head: sign-in, codes, recovery, dead links and errors share one centred head, in a
   narrow card in the middle (ui::card(gate = true), .cab-card.card-gate) with a full-width button. */
.card-gate {
  width: min(100%, 28rem);
  margin-inline: auto;
}

.card-gate > .btn {
  width: 100%;
}

.gate-head {
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  text-align: center;
}

.gate-head .empty-illo {
  margin-bottom: var(--s-2);
}

.gate-head p {
  max-width: 40ch;
  color: var(--ink-2);
}

.card-link {
  transition: border-color var(--dur-2) var(--ease);
}

.card-link:hover {
  border-color: var(--line-strong);
}

.card-link .stretched {
  text-decoration: none;
}

.card-link .stretched::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.card-link:has(.stretched:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.card-link .stretched:focus-visible {
  outline: none;
}

@media (max-width: 560px) {
  .card {
    padding: var(--s-6);
  }

  .card-head {
    flex-wrap: wrap;
  }
}

/* Dashboard: ui::kpi tiles in a .kpis row (.stat-grid/.stat-tile are the same), the
   .activity feed (who, what, when; one link per row takes the row), .progress, and
   .panel-grid for cards that wrap into columns. */
.panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  align-items: start;
  gap: var(--s-5);
}

.truncate {
  overflow: hidden;
  min-width: 0;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stat-grid,
.kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: var(--s-4);
}

/* Tiles that keep their width when there are only one or two (a list of pages). */
.kpis-fill {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
}

.stat-tile,
.kpi {
  display: grid;
  align-content: start;
  gap: var(--s-2);
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  transition: border-color var(--dur-2) var(--ease);
  container-type: inline-size;
}

a.stat-tile:hover,
a.kpi:hover {
  border-color: var(--line-strong);
}

.stat-label,
.kpi-label {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
}

.stat-label .icon,
.kpi-label .icon {
  width: 1rem;
  height: 1rem;
}

.stat-value,
.kpi-value {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.6rem + 1vw, 2.5rem);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  letter-spacing: var(--tracking-title);
  line-height: 1;
}

.stat-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-2) var(--s-3);
}

.stat-delta {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  color: var(--ink-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
}

.stat-delta.is-up {
  color: var(--success);
}

.stat-delta.is-down {
  color: var(--danger);
}

.stat-delta.is-up::before {
  content: "↑";
}

.stat-delta.is-down::before {
  content: "↓";
}

.stat-hint,
.kpi-hint,
.kpi > .muted {
  color: var(--ink-2);
  font-size: var(--fs-xs);
}

.kpi-hot {
  border-color: color-mix(in oklab, var(--accent) 35%, var(--line));
}

.kpi-hot .kpi-value,
.kpi-hot .kpi-label .icon {
  color: var(--accent-ink);
}

/* A phone keeps two tiles a row: the label wraps, and only a strip too narrow for two drops to one. */
@media (max-width: 40rem) {
  .stat-grid,
  .kpis {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
    gap: var(--s-3);
  }

  .stat-tile,
  .kpi {
    padding: var(--s-4);
  }

  /* A long number shrinks to the tile instead of breaking onto two lines. */
  .stat-value,
  .kpi-value {
    font-size: min(2rem, 22cqi);
  }
}

.activity {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.activity li {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  min-width: 0;
  padding: var(--s-3) var(--s-6);
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm);
}

.activity li:first-child {
  border-top: 0;
}

.activity li > a {
  flex: none;
  text-decoration: none;
}

/* The one link in a row takes the whole row as its target. */
.activity li:has(> a) {
  position: relative;
}

.activity li > a::after {
  content: "";
  position: absolute;
  inset: 0;
}

.activity li > a:hover {
  text-decoration: underline;
}

.activity li > .truncate {
  flex: 1;
}

.activity li > span:not(.truncate) {
  flex: 1;
  min-width: 0;
}

.activity time {
  flex: none;
  margin-inline-start: auto;
  color: var(--ink-2);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

@media (max-width: 719px) {
  .activity li {
    flex-wrap: wrap;
    gap: var(--s-1) var(--s-3);
    padding-inline: var(--s-5);
  }

  .activity li > .truncate {
    order: 3;
    flex-basis: 100%;
  }
}

.progress {
  width: 100%;
  height: 0.375rem;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--chrome-2);
  overflow: hidden;
  appearance: none;
}

.progress::-webkit-progress-bar {
  background: var(--chrome-2);
}

.progress::-webkit-progress-value {
  border-radius: var(--r-pill);
  background: var(--success);
}

.progress::-moz-progress-bar {
  border-radius: var(--r-pill);
  background: var(--success);
}

/* Showcase frames: real work shown as a product. */
.frame-browser {
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.frame-bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: 2.25rem;
  padding: 0 var(--s-3);
  border-bottom: 1px solid var(--line);
  background: var(--chrome);
}

.frame-dots {
  display: flex;
  gap: 6px;
}

.frame-dots i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--line-strong);
}

.frame-url {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  min-width: 0;
  max-width: 100%;
  padding: 0 var(--s-4);
  height: 1.5rem;
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink-2);
  font-size: var(--fs-2xs);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.frame-url .icon {
  width: 0.75rem;
  height: 0.75rem;
}

.frame-browser img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top;
}

.frame-phone {
  --bezel: clamp(5px, 0.55vw, 9px);
  margin: 0;
  padding: var(--bezel);
  border-radius: clamp(28px, 3.2vw, 48px);
  background: var(--device);
  box-shadow: var(--shadow), inset 0 0 0 1px var(--device-edge);
}

.frame-phone .frame-screen {
  position: relative;
  overflow: hidden;
  border-radius: calc(clamp(28px, 3.2vw, 48px) - var(--bezel));
  background: var(--surface);
}

.frame-phone .frame-screen::before {
  content: "";
  position: absolute;
  top: 3%;
  left: 50%; /* physical: centred by translateX(-50%), the same on both sides */
  z-index: 1;
  width: 30%;
  height: 3.6%;
  border-radius: var(--r-pill);
  background: var(--device);
  transform: translateX(-50%);
}

.frame-phone img {
  width: 100%;
  aspect-ratio: 9 / 19.5;
  object-fit: cover;
  object-position: top;
}

/* Tabs: a segmented control. */
.tabs {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border-radius: var(--r-pill);
  background: var(--chrome);
}

.tab {
  min-height: calc(var(--control-h-sm) - 6px);
  padding: 0 var(--s-4);
  border: 0;
  border-radius: var(--r-pill);
  background: none;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}

.tab:hover {
  color: var(--ink);
}

.tab[aria-selected="true"],
.tab[aria-current] {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-knob);
}

/* Breadcrumbs */
.breadcrumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--ink-2);
  font-size: var(--fs-sm);
}

.breadcrumbs li {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
}

.breadcrumbs li + li::before {
  content: "/";
  color: var(--line-strong);
}

/* The current page stays on one line, cut short if needed: its full title is the heading below. */
.breadcrumbs li:last-child {
  display: block;
  flex: 1 1 0;
  min-inline-size: 6rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.breadcrumbs li:last-child::before {
  margin-inline-end: var(--s-2);
}

.breadcrumbs a {
  text-decoration: none;
}

.breadcrumbs a:hover {
  color: var(--ink);
}

.breadcrumbs [aria-current] {
  color: var(--ink);
}

/* Menus (details/summary) */
.menu {
  position: relative;
}

.menu > summary {
  list-style: none;
  cursor: pointer;
}

.menu > summary::-webkit-details-marker {
  display: none;
}

.menu-panel {
  position: absolute;
  inset-inline-end: 0;
  top: calc(100% + var(--s-2));
  z-index: var(--z-overlay);
  min-width: 12rem;
  max-inline-size: calc(100vw - 2 * var(--gutter));
  margin: 0;
  padding: var(--s-1);
  list-style: none;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow);
  animation: rise var(--dur-2) var(--ease-out);
}

.menu-panel a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: var(--control-h-sm);
  padding: 0 var(--s-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  text-decoration: none;
}

.menu-panel a:hover {
  background: var(--chrome);
}

.menu-panel a[aria-current="true"] {
  font-weight: var(--fw-semibold);
}

.menu-panel a[aria-current="true"]::after {
  content: "";
  width: 0.875rem;
  height: 0.875rem;
  background: var(--ink);
  mask: var(--icon-check) center / contain no-repeat;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
}

/* Notices */
.notice {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--s-3);
  margin: 0;
  padding: var(--s-4);
  border-radius: var(--r-md);
  background: var(--chrome);
  color: var(--ink);
  font-size: var(--fs-sm);
}

.notice .icon {
  margin-top: 0.15em;
}

.notice > p {
  flex: 1 1 16rem;
  min-width: 0;
}

.notice > .btn {
  max-width: 100%;
  white-space: normal;
}

.notice-ok {
  background: var(--success-soft);
  color: var(--success);
}

.notice-danger {
  background: var(--danger-soft);
  color: var(--danger);
}

/* Toasts: quiet confirmation, bottom center. */
.toast-region {
  position: fixed;
  left: 50%; /* physical: centred by translateX(-50%), the same on both sides */
  bottom: calc(var(--banner-h, 0px) + max(var(--s-6), env(safe-area-inset-bottom)));
  z-index: var(--z-toast);
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  width: min(100% - 2 * var(--s-4), 28rem);
  transform: translateX(-50%);
  pointer-events: none;
}

.toast {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--control-h);
  padding: 0 var(--s-5);
  border-radius: var(--r-pill);
  background: var(--inverse);
  color: var(--on-inverse);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  box-shadow: var(--shadow);
  pointer-events: auto;
  animation: rise var(--dur-3) var(--ease-out);
}

.toast-danger {
  background: var(--danger);
  color: var(--on-danger);
}

/* Dialog (native <dialog class="dialog">) */
.dialog {
  width: min(100% - 2 * var(--s-4), 30rem);
  max-height: min(100dvh - 2 * var(--s-6), 44rem);
  padding: var(--s-7);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow);
}

.dialog[open] {
  animation: rise var(--dur-3) var(--ease-out);
}

.dialog::backdrop {
  background: color-mix(in srgb, var(--ink-base) 40%, transparent);
}

.dialog h2 {
  font-size: var(--fs-xl);
  letter-spacing: var(--tracking-snug);
}

.dialog-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--s-3);
  margin-top: var(--s-7);
}

/* Tables */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.table th,
.table td {
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--line);
  text-align: start;
  vertical-align: middle;
}

.table th {
  color: var(--ink-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  background: var(--chrome);
}

.table tr:last-child td {
  border-bottom: 0;
}

.table .num {
  text-align: end;
}

/* Check list */
.check-list {
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.check-list li {
  position: relative;
  padding-inline-start: var(--s-7);
}

.check-list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 0.3em;
  width: 1rem;
  height: 1rem;
  background: var(--ink);
  mask: var(--icon-check) center / contain no-repeat;
}

/* Steps (ui::steps, ui::step): numbered circles joined by a line. A column on narrow lists, a row
   from 40rem of list width. Done steps keep their number and get a check, the current one is in
   the accent, and the ones after it are muted. */
.steps {
  --step-dot: 2.5rem;
  container-type: inline-size;
  display: flex;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
  list-style: none;
}

.step {
  position: relative;
  display: grid;
  grid-template-columns: var(--step-dot) minmax(0, 1fr);
  align-content: start;
  gap: var(--s-4);
  flex: 1 1 100%;
  padding-bottom: var(--s-6);
}

.step:last-child {
  padding-bottom: 0;
}

.step:not(:last-child)::before {
  content: "";
  position: absolute;
  top: calc(var(--step-dot) + var(--s-1));
  bottom: var(--s-1);
  inset-inline-start: calc(var(--step-dot) / 2 - 1px);
  width: 2px;
  border-radius: var(--r-pill);
  background: var(--line-strong);
}

.step.is-done::before {
  background: var(--accent);
}

.step-dot {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--step-dot);
  height: var(--step-dot);
  border: 2px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.step.is-done .step-dot {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.step.is-current .step-dot {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: 0 0 0 4px var(--ring-color);
}

.step-check {
  position: absolute;
  inset-inline-end: -0.375rem;
  bottom: -0.375rem;
  display: grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  border: 2px solid var(--surface);
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--on-accent);
}

.step-check .icon {
  width: 0.875rem;
  height: 0.875rem;
}

.step-body {
  display: grid;
  align-content: start;
  gap: var(--s-1);
  padding-top: calc((var(--step-dot) - 1.5rem) / 2);
}

.step-label {
  margin: 0;
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  line-height: 1.5rem;
}

.step-text {
  margin: 0;
  color: var(--ink-2);
}

.step-term {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  font-size: var(--fs-xs);
}

.steps:has(.is-current) .step:not(.is-done, .is-current) .step-dot {
  border-color: var(--line);
  color: var(--ink-3);
}

.steps:has(.is-current) .step:not(.is-done, .is-current) :is(.step-label, .step-text) {
  color: var(--ink-3);
}

@container (min-width: 40rem) {
  .step {
    flex-basis: 0;
    grid-template-columns: minmax(0, 1fr);
    padding-block: 0;
    padding-inline: 0 var(--s-6);
  }

  .step:last-child {
    padding-inline-end: 0;
  }

  .step:not(:last-child)::before {
    top: calc(var(--step-dot) / 2 - 1px);
    bottom: auto;
    inset-inline-start: calc(var(--step-dot) + var(--s-2));
    inset-inline-end: var(--s-2);
    width: auto;
    height: 2px;
  }

  .step-body {
    padding-top: 0;
  }
}

/* Long-form text */
.prose {
  color: var(--ink-2);
  max-width: 68ch;
}

.prose > * + * {
  margin-top: var(--s-4);
}

.prose h2 {
  margin-top: var(--s-10);
  color: var(--ink);
  font-size: var(--fs-2xl);
}

.prose h3 {
  margin-top: var(--s-8);
  color: var(--ink);
  font-size: var(--fs-xl);
}

.prose h2 + *,
.prose h3 + * {
  margin-top: var(--s-3);
}

.prose ul,
.prose ol {
  padding-inline-start: var(--s-5);
}

.prose li + li {
  margin-top: var(--s-2);
}

.prose strong {
  color: var(--ink);
  font-weight: var(--fw-semibold);
}

.prose a {
  color: var(--accent-ink);
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.prose th,
.prose td {
  padding: var(--s-2) var(--s-3);
  border-bottom: 1px solid var(--line);
  text-align: start;
}

/* Brand */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--ink);
  text-decoration: none;
}

.brand-mark {
  width: 1.75rem;
  height: 1.75rem;
  flex: none;
}

.brand-logo {
  display: block;
  width: auto;
  height: 2rem;
  max-width: 12rem;
  object-fit: contain;
}

.brand-word {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: var(--fw-semibold);
  letter-spacing: -0.035em;
  line-height: 1;
}

.avatar {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: var(--chrome);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  object-fit: cover;
}

/* A team member's photo before their name in a client's thread. */
.avatar-msg {
  width: 2rem;
  height: 2rem;
  margin-inline-end: var(--s-2);
  vertical-align: middle;
}

.brand-square {
  fill: var(--ink);
}

.brand-gap {
  stroke: var(--ink);
}

.brand-thread {
  stroke: var(--bg);
}

/* Editor with live preview */
.editor {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  align-items: start;
  gap: var(--s-6);
}

.editor.is-preview-hidden {
  grid-template-columns: minmax(0, 1fr);
  max-width: 57.5rem;
}

.editor.is-preview-hidden .editor-preview {
  display: none;
}

.editor-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-5);
  min-width: 0;
}

.editor-preview {
  position: sticky;
  top: var(--s-6);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  height: calc(100vh - var(--topbar-h) - var(--savebar-h) - var(--s-10));
  height: calc(100dvh - var(--topbar-h) - var(--savebar-h) - var(--s-10));
  min-height: 26rem;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}

.preview-bar {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding-block: var(--s-2);
  padding-inline: var(--s-4) var(--s-2);
  border-bottom: 1px solid var(--line);
}

.preview-bar-title {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-inline-end: auto;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
}

.preview-bar .tabs > button {
  padding-inline: var(--s-3);
}

.preview-live {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--r-pill);
  background: var(--success);
}

.is-loading .preview-live {
  background: var(--warning);
  animation: pulse calc(var(--dur-3) * 3) var(--ease) infinite alternate;
}

@keyframes pulse {
  to {
    opacity: 0.35;
  }
}

.preview-stage {
  display: grid;
  justify-items: center;
  overflow: auto;
  background: var(--chrome);
}

.preview-frame {
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--surface);
  transition: width var(--dur-3) var(--ease-out);
}

.preview-stage[data-device="tablet"] .preview-frame,
.preview-stage[data-device="mobile"] .preview-frame {
  max-width: none;
  margin-block: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}

.preview-stage[data-device="tablet"] .preview-frame {
  width: 48rem;
}

.preview-stage[data-device="mobile"] .preview-frame {
  width: 24.375rem;
}

@container pane (width < 64rem) {
  .editor {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Under the form the preview grows to its page's height (admin.js sizes the frame), so the screen
     keeps one scroll and never traps a swipe inside the frame. */
  .editor-preview {
    position: relative;
    top: 0;
    order: 2;
    height: auto;
    min-height: 0;
  }

  .preview-stage {
    overflow: hidden;
  }

  .preview-frame {
    height: 70vh;
    height: 70dvh;
  }

  .preview-stage[data-device] .preview-frame {
    max-width: 100%;
  }
}

/* A phone is the device already: the size switch would only shrink the page. */
@media (max-width: 719px) {
  .preview-bar .tabs {
    display: none;
  }

  .preview-bar {
    min-height: var(--control-h);
  }
}

/* Page blocks */
.block-list {
  display: grid;
  gap: var(--s-2);
}

/* The empty state of a page leaves once its first block is added. */
.block-list:has(.block-item) + .empty {
  display: none;
}

.block-item {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  transition: border-color var(--dur-2) var(--ease);
}

.block-item:has(details[open]) {
  border-color: var(--line-strong);
}

.block-item.is-off .block-title strong {
  color: var(--ink-2);
  text-decoration: line-through;
}

.block-item.is-off .block-icon {
  background: var(--chrome);
  color: var(--ink-3);
}

.block-switch {
  position: absolute;
  top: calc(var(--s-3) + 0.875rem);
  inset-inline-end: calc(var(--s-4) + 2rem);
  z-index: 1;
}

.block-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 4rem;
  padding-block: var(--s-3);
  padding-inline: var(--s-2) calc(var(--s-4) + 5.5rem);
  list-style: none;
  cursor: pointer;
}

.block-head::-webkit-details-marker {
  display: none;
}

.block-head > .icon {
  position: absolute;
  top: 1.5rem;
  inset-inline-end: var(--s-4);
  color: var(--ink-2);
  transition: transform var(--dur-2) var(--ease);
}

.block-item details[open] .block-head > .icon {
  transform: rotate(180deg);
}

.block-icon {
  display: grid;
  flex: none;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.block-title {
  display: grid;
  flex: 1;
  min-width: 0;
  line-height: 1.35;
}

.block-title strong {
  overflow: hidden;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.block-title small {
  overflow: hidden;
  color: var(--ink-2);
  font-size: var(--fs-xs);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.block-body {
  display: grid;
  gap: var(--s-5);
  padding: var(--s-5);
  border-top: 1px solid var(--line);
}

.block-add {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 11rem), 1fr));
  gap: var(--s-2);
}

.block-add button {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--s-2);
  min-height: var(--control-h);
  padding: 0 var(--s-3);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  background: none;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  text-align: start;
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease), background-color var(--dur-1) var(--ease);
}

.block-add button:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-ink);
}

@media (max-width: 719px) {
  .block-body {
    padding: var(--s-4);
  }

  /* On a phone the block name needs the room more than its icon. */
  .block-head .block-icon {
    display: none;
  }
}

/* A card on its own in the preview of a collection editor */
.preview-card-stage {
  padding: var(--s-8);
  border-radius: var(--r-lg);
  background: var(--chrome);
}

.preview-card-stage > * {
  max-width: 400px;
}
/* List titles: a long word (a setting name, a link) wraps instead of widening the row on phones. */
.cell-main a {
  overflow-wrap: anywhere;
}

/* Collection lists: on touch screens a record's title is a full-size target. */
@media (pointer: coarse) {
  .cell-main a {
    display: inline-flex;
    align-items: center;
    min-height: var(--target-min);
  }
}

/* Canvas: an editor whose result is a page of the site (ui.html "Canvas editor"). The form on the
   left, the page in a browser window on the right, sticky while the form scrolls; under the form
   where the pane is narrower than 47.5rem, the frame then as tall as its page (admin.js). */
.canvas-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: var(--s-6);
  max-width: 86rem;
  margin-inline: auto;
}

.canvas-form {
  align-content: start;
}

.canvas-stage {
  display: grid;
  grid-template-rows: auto auto;
  justify-items: center;
  align-content: start;
  gap: var(--s-3);
  min-width: 0;
  padding: var(--s-6);
  border-radius: var(--r-xl);
  background: color-mix(in oklab, var(--chrome-2) 70%, transparent);
}

.canvas-frame {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow);
  transition: width var(--dur-3) var(--ease-out);
}

.canvas-frame[data-device="mobile"] {
  width: 22.5rem;
  max-width: 100%;
  border: 8px solid var(--device);
  border-radius: 2.25rem;
}

.canvas-chrome {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-4);
  border-bottom: 1px solid var(--line);
  background: var(--chrome);
}

.canvas-frame[data-device="mobile"] .canvas-chrome {
  display: none;
}

.canvas-dots {
  display: flex;
  flex: none;
  gap: 6px;
}

.canvas-dots i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--line-strong);
}

.canvas-url {
  flex: 1;
  min-width: 0;
  margin-inline-start: var(--s-2);
  padding: var(--s-1) var(--s-3);
  overflow: hidden;
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  text-decoration: none;
  text-overflow: ellipsis;
  white-space: nowrap;
}

a.canvas-url:hover {
  color: var(--accent-ink);
}

/* The page is laid out at a desktop's width and scaled down to the window (admin.js sets
   --canvas-scale), as a visitor at a computer sees it; at a phone's width and in the phone frame it
   takes the width it has. */
.canvas-view {
  position: relative;
  flex: none;
  height: 70vh;
  height: 70dvh;
  min-height: 0;
  overflow: hidden;
}

.canvas-page {
  position: absolute;
  top: 0;
  inset-inline-start: 0;
  display: block;
  width: 1280px;
  height: calc(100% / var(--canvas-scale, 1));
  border: 0;
  background: var(--surface);
  transform: scale(var(--canvas-scale, 1));
  transform-origin: 0 0;
}
[dir="rtl"] .canvas-page {
  transform-origin: 100% 0;
}

.canvas-frame[data-device="mobile"] .canvas-page {
  width: 100%;
}

@container pane (width < 30rem) {
  .canvas-page {
    width: 100%;
  }
}

.canvas-hint {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--fs-sm);
  text-align: center;
}

@container pane (min-width: 47.5rem) {
  .canvas-body {
    grid-template-columns: minmax(18rem, 22rem) minmax(0, 1fr);
  }

  .canvas-stage {
    position: sticky;
    top: 0;
    grid-template-rows: minmax(0, 1fr) auto;
    height: calc(100vh - var(--topbar-h) - 2 * var(--s-6));
    height: calc(100dvh - var(--topbar-h) - 2 * var(--s-6));
    min-height: 26rem;
  }

  .canvas-frame {
    height: 100%;
  }

  .canvas-view {
    flex: 1;
    height: auto;
  }

  .canvas-peek {
    display: none;
  }
}

body.is-dirty [data-clean-text],
body:not(.is-dirty) [data-dirty-text] {
  display: none;
}

/* Publish: "Published" at rest on a live page with nothing new, "Publish" once there is. */
[data-publish] > span {
  display: contents;
}

[data-publish="live"]:not(:disabled) .publish-done,
[data-publish="live"]:disabled .publish-go {
  display: none;
}

.btn-primary[data-publish]:disabled {
  background: var(--success-soft);
  color: var(--success);
  opacity: 1;
}

/* Full screen and back: one button, its icon and words follow its state. */
.canvas-full[aria-pressed="false"] .icon:nth-of-type(2),
.canvas-full[aria-pressed="true"] .icon:first-of-type,
.canvas-full[aria-pressed="false"] .btn-label > span:last-child,
.canvas-full[aria-pressed="true"] .btn-label > span:first-child {
  display: none;
}

/* Pages in the list pane, under their section: a page in miniature, its name, address and state. */
.page-rows {
  margin: 2px 0 var(--s-2);
}

.seg-n {
  color: var(--ink-3);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}

.page-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--control-h);
  padding: var(--s-2);
  border-radius: var(--r-md);
  color: var(--ink);
  text-decoration: none;
  transition: background-color var(--dur-1) var(--ease);
}

.page-row:hover {
  background: var(--chrome);
}

.page-row[aria-current="page"] {
  background: var(--accent-soft);
}

.page-row-text {
  display: grid;
  flex: 1;
  gap: 2px;
  min-width: 0;
}

.page-row-text > * {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.page-row-text small {
  color: var(--ink-3);
  font-size: var(--fs-xs);
}

.page-row .badge {
  flex: none;
}

.slug-moved {
  margin-top: var(--s-2);
}

/* Segmented switch: links to the same screen with one option each, the current one raised. */
.seg {
  display: inline-flex;
  gap: var(--s-1);
  padding: var(--s-1);
  border-radius: var(--r-lg);
  background: var(--chrome-2);
}

.seg > a,
.seg > button {
  display: inline-flex;
  align-items: center;
  min-height: var(--target-min, 2.75rem);
  padding: 0 var(--s-4);
  border-radius: var(--r-md);
  color: var(--ink-2);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  text-decoration: none;
  transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}

.seg > button {
  border: 0;
  background: none;
  font-family: inherit;
  cursor: pointer;
}

.seg > a:hover,
.seg > button:hover {
  color: var(--ink);
}

.seg > a[aria-current],
.seg > button[aria-pressed="true"] {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--lift);
}

/* Sparkline: a line over a soft area ending in a dot, what its points are written under it. */
.sparkline {
  display: grid;
  gap: var(--s-1);
  min-width: 0;
  margin: 0;
  color: var(--accent);
}

.sparkline svg {
  display: block;
  width: 100%;
  height: 2.5rem;
  overflow: visible;
}

.sparkline-area {
  fill: currentColor;
  opacity: 0.1;
}

.sparkline-line,
.sparkline-dot {
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.sparkline-line {
  stroke-width: 2.5;
}

.sparkline-dot {
  stroke-width: 7;
}

.sparkline figcaption {
  color: var(--ink-3);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
}

.sparkline-ok {
  color: var(--success);
}

.sparkline-warn {
  color: var(--warning);
}

/* Tile: one area with its number, sparkline and latest records. The title's link covers the
   tile; chips and records sit above it and open their own filter or record. */
.tiles {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-4);
}

@media (min-width: 600px) {
  .tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tile-wide {
    grid-column: span 2;
  }
}

@media (min-width: 1100px) {
  .tiles {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--s-6);
  }

  .tile-half {
    grid-column: span 2;
  }
}

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  min-width: 0;
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--lift);
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease);
}

.tile:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow), var(--lift);
}

.tile:has(.tile-head a:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.tile-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
}

.tile-head h3 {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: var(--fs-lg);
}

.tile-head a {
  color: inherit;
  text-decoration: none;
}

.tile-head a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.tile-head a:focus-visible {
  outline: 0;
}

.tile-head > .icon {
  color: var(--ink-3);
}

.tile:hover .tile-head > .icon {
  color: var(--accent-ink);
}

.tile-icon {
  display: grid;
  flex: none;
  place-items: center;
  width: var(--target-min, 2.75rem);
  height: var(--target-min, 2.75rem);
  border-radius: var(--r-md);
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.tile-icon-ok {
  background: var(--success-soft);
  color: var(--success);
}

.tile-icon-warn {
  background: var(--warning-soft);
  color: var(--warning);
}

.tile-icon-gray {
  background: var(--chrome-2);
  color: var(--ink-2);
}

.tile-kpi {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.tile-num {
  margin: 0;
  font-size: var(--fs-2xl);
  font-weight: 800;
  letter-spacing: var(--tracking-title);
  line-height: 1;
}

.tile-num small {
  display: block;
  margin-top: var(--s-2);
  color: var(--ink-3);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: 0;
  line-height: 1.3;
}

.tile-wide .tile-num {
  font-size: var(--fs-3xl);
}

@media (min-width: 1100px) {
  .tile-wide .tile-kpi {
    flex-direction: row;
    align-items: end;
  }

  .tile-wide .tile-num {
    flex: 1;
    min-width: 0;
  }

  .tile-wide .sparkline {
    width: 55%;
  }

  .tile-wide .sparkline svg {
    height: 4.5rem;
  }
}

.tile-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.tile-chips a,
.tile-items a {
  position: relative;
  z-index: 1;
}

.tile-chips a {
  min-height: 2rem;
  padding-inline: var(--s-3);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  text-decoration: none;
}

.tile-chips a:hover {
  box-shadow: inset 0 0 0 1px currentColor;
}

.tile-items {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  margin: auto 0 0;
  padding: 0;
  border-top: 1px solid var(--line);
  list-style: none;
}

.tile-items:first-child {
  border-top: 0;
}

.tile-items li + li {
  border-top: 1px solid var(--line);
}

.tile-items a,
.tile-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-width: 0;
  min-height: var(--target-min, 2.75rem);
  padding: var(--s-2) 0;
  color: inherit;
  font-size: var(--fs-sm);
  text-decoration: none;
}

.tile-items li:last-child a,
.tile-items li:last-child .tile-row {
  padding-bottom: 0;
}

.tile-items a:hover b {
  color: var(--accent-ink);
}

.tile-item-text {
  flex: 1;
  min-width: 0;
}

.tile-item-text > * {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tile-item-text b {
  font-weight: var(--fw-semibold);
}

.tile-item-text span {
  color: var(--ink-3);
}

.tile-items time {
  flex: none;
  color: var(--ink-3);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}

.tile-mark {
  flex: none;
  width: 2rem;
  height: 2rem;
  border-radius: var(--r-sm);
  object-fit: cover;
}

.tile-mark.avatar {
  border-radius: 50%;
  font-size: var(--fs-2xs);
}

.tile-mark.tile-icon .icon {
  width: 1rem;
  height: 1rem;
}

/* How to pay an invoice (partials/pay.html): one card per payment method, the same on the client's
   cabinet and on the public invoice page. */
.pay-list {
  display: grid;
  gap: var(--s-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.pay-item {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

.pay-item h3,
.pay-item p {
  margin: 0;
}

.pay-total {
  font-weight: var(--fw-semibold);
}

.pay-facts {
  display: grid;
  gap: var(--s-4);
  margin: 0;
}

.pay-facts dt {
  color: var(--ink-3);
  font-size: var(--fs-sm);
}

.pay-facts dd {
  margin: 0;
}

.pay-mono {
  font-family: var(--font-mono);
  overflow-wrap: anywhere;
}

.pay-link {
  min-height: 44px;
  max-width: 100%;
}

.pay-qr {
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-sm);
}

.pay-qr svg {
  display: block;
  width: 12rem;
  height: auto;
  margin-bottom: var(--s-2);
}

@media (min-width: 640px) {
  .pay-facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media print {
  .pay-link {
    display: none !important;
  }
}

/* Public site: shell, home blocks and inner pages. Built on tokens.css and components.css. */

/* ---------- Shell ---------- */

.skip-link {
  position: absolute;
  top: var(--s-2);
  inset-inline-start: var(--s-2);
  z-index: calc(var(--z-header) + 1);
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--bg);
  font-weight: var(--fw-medium);
  text-decoration: none;
  transform: translateY(-200%);
}
.skip-link:focus-visible {
  transform: none;
}

.brand {
  min-height: 2.75rem;
}

/* The sticky header is always in view: its controls cancel the page's top scroll padding, so
   focusing one (Tab, or the burger after the menu closes) never scrolls the page. */
.site-header * {
  scroll-margin-top: calc(-1 * (var(--header-h) + var(--s-4)));
}
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  border-bottom: 1px solid transparent;
  background: var(--bg);
  transition: border-color var(--dur-2) var(--ease);
}
/* The no-JS menu opens inside the header, so the header rises over the cookie bar while it is open. */
.site-header:has(.menu-fallback[open]) {
  z-index: var(--z-overlay);
}
.site-header[data-scrolled] {
  border-bottom-color: var(--line);
}
.header-inner {
  display: flex;
  align-items: center;
  gap: var(--s-6);
  min-height: var(--header-h);
}
.main-nav > ul {
  display: flex;
  gap: var(--s-1);
  margin: 0;
  padding: 0;
  list-style: none;
}
.main-nav > ul > li > a {
  display: block;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-pill);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-decoration: none;
  transition: color var(--dur-1) var(--ease), background-color var(--dur-1) var(--ease);
}
.main-nav > ul > li > a:hover,
.main-nav .menu > summary:hover {
  background: var(--chrome);
  color: var(--ink);
}
.main-nav > ul > li > a[aria-current="page"] {
  color: var(--ink);
}
/* An item with nested ones: the link, then the arrow that opens them. */
.main-nav li:has(> .menu) {
  display: flex;
  align-items: center;
}
.main-nav .menu > summary {
  display: grid;
  place-items: center;
  width: var(--control-h-sm);
  height: var(--control-h-sm);
  border-radius: var(--r-pill);
  color: var(--ink-3);
  transition: color var(--dur-1) var(--ease), background-color var(--dur-1) var(--ease);
}
.main-nav .menu[open] > summary .icon {
  transform: rotate(180deg);
}
.main-nav .menu-panel {
  inset-inline: 0 auto;
}
.menu-panel ul {
  margin: 0;
  padding: 0;
  padding-inline-start: var(--s-3);
  list-style: none;
}
.header-actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-inline-start: auto;
}
.lang-code {
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
.lang-menu .menu-panel a {
  display: flex;
  justify-content: space-between;
  gap: var(--s-6);
}
.lang-menu .menu-panel .lang-code {
  color: var(--ink-3);
}

.theme-toggle[aria-pressed="false"] .icon:first-child,
.theme-toggle[aria-pressed="true"] .icon:last-child {
  display: none;
}

/* Menu sheet on narrow screens: a native modal dialog, so the page behind is inert and Esc closes it. */
.menu-toggle,
.menu-fallback {
  display: none;
}
.menu-fallback .menu-panel a {
  min-height: 2.75rem;
}
.menu-fallback-cta {
  padding: var(--s-2) var(--s-1) var(--s-1);
}
.menu-fallback .menu-fallback-cta a,
.menu-fallback .menu-fallback-cta a:hover {
  justify-content: center;
  background: var(--accent);
  color: var(--on-accent);
}
.menu-fallback li:not(:has([hreflang])) + li:has([hreflang]) {
  margin-top: var(--s-1);
  padding-top: var(--s-1);
  border-top: 1px solid var(--line);
}
.site-menu {
  inset-block: 0;
  inset-inline: auto 0;
  width: min(26rem, 100% - var(--s-9));
  max-width: none;
  height: 100dvh;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  border-inline-start: 1px solid var(--line);
  background: var(--bg);
  color: var(--ink);
  overscroll-behavior: contain;
}
.site-menu[open] {
  display: flex;
  flex-direction: column;
  animation: sheet-in var(--dur-3) var(--ease-out);
}
.site-menu::backdrop {
  background: color-mix(in srgb, var(--ink-base) 40%, transparent);
  animation: fade-in var(--dur-3) var(--ease-out);
}
.site-menu[data-closing] {
  animation: sheet-out var(--dur-2) var(--ease) forwards;
}
.site-menu[data-closing]::backdrop {
  animation: fade-out var(--dur-2) var(--ease) forwards;
}
@keyframes sheet-in {
  from {
    transform: translateX(calc(100% * var(--dir)));
  }
}
@keyframes sheet-out {
  to {
    transform: translateX(calc(100% * var(--dir)));
  }
}
@keyframes fade-in {
  from {
    opacity: 0;
  }
}
@keyframes fade-out {
  to {
    opacity: 0;
  }
}
:root {
  scrollbar-gutter: stable;
}
:root:has(.site-menu[open]) {
  overflow: hidden;
}
.site-menu-head {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: var(--header-h);
  padding: env(safe-area-inset-top) max(var(--gutter), env(safe-area-inset-right)) 0 max(var(--gutter), env(safe-area-inset-left)); /* physical: the screen's cut-outs are physical sides */
  border-bottom: 1px solid var(--line);
}
.site-menu-body {
  display: grid;
  flex: 1;
  align-content: start;
  gap: var(--s-7);
  overflow-y: auto;
  padding: var(--s-2) max(var(--gutter), env(safe-area-inset-right)) var(--s-7) max(var(--gutter), env(safe-area-inset-left)); /* physical: the screen's cut-outs are physical sides */
}
.site-menu-nav,
.site-menu-langs,
.site-menu-contacts {
  margin: 0;
  padding: 0;
  list-style: none;
}
.site-menu-nav ul {
  margin: 0;
  padding: 0;
  padding-inline-start: var(--s-4);
  list-style: none;
}
.site-menu-nav ul a {
  min-height: var(--control-h);
  font-size: var(--fs-lg);
}
.site-menu-nav a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: 3.5rem;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-snug);
  text-decoration: none;
}
.site-menu-nav .icon {
  flex: none;
  color: var(--ink-3);
  transition: translate var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.site-menu-nav a:hover .icon {
  color: var(--ink);
  translate: calc(2px * var(--dir));
}
.site-menu-nav a[aria-current="page"] {
  box-shadow: inset 2px 0 0 var(--ink);
  padding-inline-start: var(--s-4);
}
.site-menu-group {
  display: grid;
  gap: var(--s-2);
}
.site-menu-title {
  margin: 0;
  color: var(--ink-3);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
.site-menu-langs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr));
  gap: var(--s-2);
}
.site-menu-langs a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  min-height: var(--control-h);
  padding-inline: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--ink);
  font-weight: var(--fw-medium);
  text-decoration: none;
}
.site-menu-langs .lang-code {
  color: var(--ink-3);
}
.site-menu-langs a[aria-current="true"] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}
.site-menu-contacts a {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--control-h);
  color: var(--ink);
  overflow-wrap: anywhere;
  text-decoration: none;
}
.site-menu-contacts .icon {
  flex: none;
  color: var(--ink-3);
}
.site-menu-foot {
  flex: none;
  padding: var(--s-4) max(var(--gutter), env(safe-area-inset-right)) max(var(--s-4), env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left)); /* physical: the screen's cut-outs are physical sides */
  border-top: 1px solid var(--line);
}
.site-menu-foot .btn {
  width: 100%;
}

@media (max-width: 959px), (max-height: 500px) {
  .main-nav,
  .lang-menu {
    display: none;
  }
  .menu-toggle:not([hidden]) {
    display: inline-flex;
  }
  .menu-fallback:not([hidden]) {
    display: block;
  }
}
@media (max-width: 479px) {
  .header-cta {
    display: none;
  }
}

.site-footer {
  margin-top: var(--section-y);
  border-top: 1px solid var(--line);
  color: var(--ink-2);
  font-size: var(--fs-sm);
}
.footer-grid {
  display: grid;
  gap: var(--s-10) var(--s-8);
  padding-block: var(--s-12) var(--s-10);
}
@media (min-width: 640px) {
  .footer-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (min-width: 1024px) {
  .footer-grid {
    grid-template-columns: 1.6fr 1fr 1fr 1.4fr;
  }
}
.footer-grid h2 {
  margin: 0 0 var(--s-4);
  color: var(--ink-3);
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
.footer-grid ul {
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer-grid ul ul {
  margin-top: var(--s-2);
  padding-inline-start: var(--s-3);
}
.footer-grid a,
.footer-bottom a {
  color: inherit;
  text-decoration: none;
}
.footer-grid a:hover,
.footer-bottom a:hover {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.footer-brand p {
  max-width: 30ch;
  margin: var(--s-4) 0 0;
}
.socials {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-5);
}
.socials a {
  display: grid;
  flex: none;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--ink-2);
  transition: border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.socials a:hover {
  border-color: var(--line-strong);
  color: var(--ink);
  text-decoration: none;
}
.requisites {
  display: grid;
  /* A long legal form name must not squeeze the value into a column one letter wide. */
  grid-template-columns: fit-content(40%) minmax(0, 1fr);
  gap: var(--s-1) var(--s-3);
  margin: var(--s-6) 0 0;
  color: var(--ink-3);
  font-size: var(--fs-xs);
}
.requisites dt {
  font-weight: var(--fw-medium);
}
.requisites dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
/* The footer column is narrow: each label sits above its value. */
.footer-grid .requisites {
  grid-template-columns: minmax(0, 1fr);
  row-gap: 0;
}
.footer-grid .requisites dd + dt {
  margin-top: var(--s-2);
}
.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3) var(--s-6);
  padding-block: var(--s-6) var(--s-8);
  border-top: 1px solid var(--line);
  color: var(--ink-3);
}
.footer-bottom > span {
  margin-inline-end: auto;
}
.footer-langs {
  display: flex;
  gap: var(--s-4);
}
.footer-langs a[aria-current] {
  color: var(--ink);
  font-weight: var(--fw-medium);
}
/* A language named in another script keeps the system face: «Русский» on a Latin page doesn't
   fetch the Cyrillic font file just for itself. */
:root:not(:lang(ru)) :is(.lang-menu, .site-menu-langs, .footer-langs) a:lang(ru),
:root:lang(ru) :is(.lang-menu, .site-menu-langs, .footer-langs) a:not(:lang(ru)) {
  font-family: var(--font-system);
}

/* ---------- Sections ---------- */

.section {
  padding-block: calc(var(--section-y) / 2);
}
main > .section:first-child,
.page-hero + .section {
  padding-top: var(--s-10);
}
.section-tight {
  padding-block: calc(var(--section-y) / 4);
}
.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-4) var(--s-8);
  margin-bottom: var(--s-10);
}
.section-head > div {
  max-width: 44rem;
}
/* A bare heading with its lead stacks at the start; a head holding only the all-items link puts it at the end. */
.section-head:not(:has(> div)) {
  display: block;
  margin-bottom: var(--s-6);
}
.section-head:has(> .more-link:only-child) {
  display: flex;
  justify-content: flex-end;
}
.section-title {
  margin: 0;
  font-size: var(--fs-3xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-title);
  text-wrap: balance;
}
/* A heading with its text or list in a detail page's column: close together, apart from the next pair. */
.detail-part {
  display: grid;
  gap: var(--s-3);
}
.stack:has(> .detail-part) {
  gap: var(--s-8);
}
.section-head .lead {
  margin-top: var(--s-4);
}
.section-head .eyebrow,
.page-hero .eyebrow,
.hero .eyebrow {
  margin-bottom: var(--s-4);
}

/* ---------- Hero ---------- */

.hero {
  padding-block: var(--s-10) calc(var(--section-y) / 2);
}
.hero-title {
  max-width: 17ch;
  margin: 0;
  font-size: clamp(2.5rem, 1.1rem + 5.6vw, 5.75rem);
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
}
.hero-title .thought,
.section-title .thought {
  display: block;
}
.hero-aside {
  display: grid;
  gap: var(--s-6);
  margin-top: var(--s-8);
}
.hero-aside .lead {
  max-width: 34rem;
  margin: 0;
}
@media (min-width: 960px) {
  .hero-aside {
    grid-template-columns: minmax(0, 34rem) auto;
    align-items: end;
    justify-content: space-between;
  }
}

/* The phone hangs over the frame's bottom corner; the caption under the frame keeps clear of it. */
.showcase {
  position: relative;
  margin: var(--s-12) 0 0;
  padding-inline-end: 9%;
  padding-block-end: 7%;
}
.showcase-phone {
  position: absolute;
  inset-inline-end: 0;
  inset-block-end: 0;
  width: 21%;
}
.showcase-caption {
  margin-block-start: var(--s-5);
  padding-inline-end: calc(13% + var(--s-4)); /* the phone's 21% less the figure's 9%, measured against the caption's 91% */
  font-size: var(--fs-sm);
}
@media (max-width: 599px) {
  .showcase {
    margin-block-start: var(--s-10);
    padding-inline-end: 18%;
    padding-block-end: 14%;
  }
  .showcase-phone {
    width: 34%;
  }
  .showcase-caption {
    padding-inline-end: calc(20% + var(--s-4)); /* 34% less 18%, against 82% */
  }
}
.hero-points {
  display: grid;
  gap: var(--s-3) var(--s-8);
  margin: var(--s-10) 0 0;
  padding: var(--s-5) 0 0;
  border-top: 1px solid var(--line);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  list-style: none;
}
@media (min-width: 768px) {
  .hero-points {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
.hero-points li {
  display: flex;
  gap: var(--s-2);
}
.hero-points li::before {
  content: "";
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 0.2em;
  background: var(--ink);
  mask: var(--icon-check) center / contain no-repeat;
}

/* ---------- Stats ---------- */

.stats {
  display: grid;
  gap: var(--s-8) var(--s-6);
}
@media (min-width: 560px) {
  .stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (min-width: 1024px) {
  .stats {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
.stat {
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
}
.stat strong {
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: var(--tracking-title);
}
.stat span {
  max-width: 26ch;
  color: var(--ink-2);
  font-size: var(--fs-sm);
}

/* ---------- Services: a price index ---------- */

.service-list {
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line-strong);
  list-style: none;
}
.service-row {
  position: relative;
  display: grid;
  grid-template-areas: "title go" "summary summary" "price price";
  grid-template-columns: 1fr auto;
  gap: var(--s-2) var(--s-6);
  padding-block: var(--s-6);
  border-bottom: 1px solid var(--line);
}
@media (min-width: 960px) {
  .service-row {
    grid-template-areas: "title summary price go";
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 0.8fr) 24px;
    align-items: baseline;
    padding-block: var(--s-7);
  }
}
.service-title {
  grid-area: title;
  margin: 0;
  font-size: var(--fs-xl);
  letter-spacing: var(--tracking-snug);
}
.service-title .badge {
  margin-inline-start: var(--s-3);
  vertical-align: 0.15em;
}
.service-title a {
  color: inherit;
  text-decoration: none;
}
.stretched::after {
  content: "";
  position: absolute;
  inset: 0;
}
.service-summary {
  grid-area: summary;
  max-width: 44ch;
  margin: 0;
  color: var(--ink-2);
}
.service-price {
  grid-area: price;
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s-2);
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-sm);
}
.service-price .price {
  flex-basis: 100%;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
}
.service-price span:not(.price) + span::before {
  content: "·";
  margin-inline-end: var(--s-2);
}
.service-price .service-pay {
  flex-basis: 100%;
}
.service-price span:not(.price) + span.service-pay::before {
  content: none;
}
.service-go {
  grid-area: go;
  align-self: center;
  color: var(--ink-3);
  transition: color var(--dur-1) var(--ease), translate var(--dur-2) var(--ease-out);
}
.service-row:hover .service-go {
  color: var(--ink);
  translate: calc(4px * var(--dir));
}
.service-row:hover .service-title {
  color: var(--accent-ink);
}
.service-row:has(.stretched:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: var(--r-sm);
}
.service-row .stretched:focus-visible {
  outline: none;
}
.services-note {
  margin-top: var(--s-6);
  color: var(--ink-3);
  font-size: var(--fs-sm);
}
.oneoff-note {
  display: block;
  font-size: var(--fs-sm);
}
.oneoff-term {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-sm);
}
/* On a phone the first services follow the page title straight away, so a price is on the first screen;
   screen readers still hear the first category's title. */
@media (max-width: 959px) {
  .service-category:first-of-type .section-head {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
}

/* ---------- Cases ---------- */

.case-list {
  display: grid;
  gap: var(--s-6);
}
.case-card {
  --pad: clamp(var(--s-6), 4vw, var(--s-10));
  position: relative;
  display: grid;
  gap: var(--s-8);
  overflow: hidden;
  padding: var(--pad) var(--pad) 0;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--chrome);
  transition: border-color var(--dur-2) var(--ease);
}
@media (min-width: 960px) {
  .case-card {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--s-10);
  }
}
.case-card:hover {
  border-color: var(--line-strong);
}
.case-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-4);
  overflow-wrap: anywhere;
}
@media (min-width: 960px) {
  .case-body {
    padding-bottom: var(--pad);
  }
}
.case-client {
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-sm);
}
.case-client span::before {
  content: " · ";
}
.case-card h3 {
  margin: 0;
  font-size: var(--fs-2xl);
  letter-spacing: var(--tracking-title);
  text-wrap: balance;
}
.case-card h3 a {
  color: inherit;
  text-decoration: none;
}
.case-summary {
  margin: 0;
  color: var(--ink-2);
}
.case-body .more-link {
  margin-top: auto;
  padding-top: var(--s-4);
}
.case-frame {
  align-self: end;
  margin-inline-end: calc(var(--pad) * -1);
  border-inline-end: 0;
  border-bottom: 0;
  border-radius: 0;
  border-start-start-radius: var(--r-md);
  transition: transform var(--dur-3) var(--ease-out);
}
.case-card:hover .case-frame {
  transform: translateY(-4px);
}
.case-cover-empty {
  aspect-ratio: 16 / 10;
  background: var(--chrome-2);
}
.case-card:has(.stretched:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.case-card .stretched:focus-visible {
  outline: none;
}

/* ---------- Blog cards ---------- */

/* Compact cards: a 16:9 picture, a meta line, a title of up to three lines and a short excerpt. */
.post-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
  gap: var(--s-6);
}
.post-card {
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  transition: border-color var(--dur-2) var(--ease);
}
.post-card:hover {
  border-color: var(--line-strong);
}
.post-card:has(.stretched:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.post-card .stretched:focus-visible {
  outline: none;
}
.post-media {
  aspect-ratio: 16 / 9;
  border-bottom: 1px solid var(--line);
  background: var(--chrome);
}
.post-media img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}
/* A post without a cover: the first letter of its title on an accent tint, never an empty frame. */
.post-tile {
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-size: var(--fs-4xl);
  font-weight: var(--fw-semibold);
  line-height: 1;
}
.post-body {
  display: grid;
  align-content: start;
  gap: var(--s-2);
  padding: var(--s-5);
  overflow-wrap: anywhere;
}
.post-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s-2);
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-xs);
}
.post-meta > * + *::before {
  content: "·";
  margin-inline-end: var(--s-2);
}
.post-card h3 {
  margin: 0;
  font-size: var(--fs-lg);
  line-height: 1.3;
  text-wrap: pretty;
}
/* The link itself is clamped, so its box (where focus scrolls to) is the three lines shown. */
.post-card h3 a {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
}
.post-excerpt {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  margin: 0;
  color: var(--ink-2);
  font-size: var(--fs-sm);
}
.post-author {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-xs);
}

/* ---------- Split layout: features and FAQ ---------- */

.split {
  display: grid;
  gap: var(--s-8);
}
@media (min-width: 960px) {
  .split {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--s-12);
  }
  .split-head {
    position: sticky;
    top: calc(var(--header-h) + var(--s-8));
    align-self: start;
  }
}
.split-head .section-head {
  margin-bottom: 0;
}
.split-head:not(:has(*)) {
  display: none;
}
.split-head:not(:has(*)) + * {
  grid-column: 1 / -1;
}

.spec {
  margin: 0;
  border-top: 1px solid var(--line-strong);
}
.spec-row {
  display: grid;
  gap: var(--s-2) var(--s-6);
  padding-block: var(--s-5);
  border-bottom: 1px solid var(--line);
}
@media (min-width: 600px) {
  .spec-row {
    grid-template-columns: 13rem 1fr;
  }
}
.spec dt {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-weight: var(--fw-medium);
}
.spec dt .icon {
  color: var(--ink-3);
}
.spec dd {
  margin: 0;
  color: var(--ink-2);
}

.faq details {
  border-bottom: 1px solid var(--line);
}
.faq details:first-child {
  border-top: 1px solid var(--line-strong);
}
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-6);
  padding-block: var(--s-5);
  font-size: var(--fs-lg);
  font-weight: var(--fw-medium);
  list-style: none;
  cursor: pointer;
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary .icon {
  flex: none;
  color: var(--ink-3);
  transition: transform var(--dur-2) var(--ease-out);
}
.faq details[open] summary .icon {
  transform: rotate(45deg);
}
.faq summary:hover .icon {
  color: var(--ink);
}
.faq .prose {
  max-width: 62ch;
  padding-bottom: var(--s-6);
  color: var(--ink-2);
}

/* ---------- Reviews and promos ---------- */

/* Fixed columns for a row of equal cards: 1, 2 from 640px, 3 from 960px. */
.card-grid {
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 640px) {
  .card-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (min-width: 960px) {
  .card-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.review {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  margin: 0;
}
.stars {
  display: flex;
  gap: 2px;
  color: var(--ink);
}
.stars .icon {
  width: 16px;
  height: 16px;
  fill: currentColor;
  stroke: none;
}
.stars .icon.off {
  color: var(--line-strong);
}
.review blockquote {
  flex: 1;
  margin: 0;
  font-size: var(--fs-lg);
  line-height: 1.5;
  white-space: pre-line;
}
/* A long review from the cabinet is cut to eight lines, so one text does not stretch its whole row;
   site.js shows «Читать дальше» under a cut text. Without scripts the text stays whole. */
.js .review blockquote > span:not(.is-open) {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 8;
}
.review blockquote > button {
  display: block;
  margin-block-start: var(--s-2);
  color: var(--accent-ink);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
}
.review figcaption {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-5);
}
.review figcaption footer {
  display: flex;
  align-items: center;
  align-self: stretch;
  gap: var(--s-3);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
}
.review figcaption .more-link {
  order: -1;
}
/* Room for a name and a role even without the role, so the dividers in a row stay on one line. */
.review cite {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc((1rem + var(--fs-sm)) * var(--lh-body));
  font-style: normal;
  font-weight: var(--fw-medium);
}
.review cite span {
  display: block;
  color: var(--ink-3);
  font-size: var(--fs-sm);
  font-weight: var(--fw-regular);
}

.promo {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.promo h3,
.promo p {
  margin: 0;
}
.promo-discount {
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: var(--tracking-title);
}
.promo-code {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-1) var(--s-3);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-sm);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
}
.promo-ends {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.service-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  margin-top: auto;
  padding-top: var(--s-3);
  font-size: var(--fs-sm);
}

/* ---------- CTA band ---------- */

.cta-band {
  display: grid;
  gap: var(--s-8);
  padding: clamp(var(--s-8), 6vw, var(--s-12));
  border-radius: var(--r-xl);
  background: var(--inverse);
  color: var(--on-inverse);
}
@media (min-width: 960px) {
  .cta-band {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    align-items: end;
    gap: var(--s-12);
  }
}
.cta-band h2 {
  margin: 0;
  color: inherit;
  font-size: var(--fs-3xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-title);
  text-wrap: balance;
}
.cta-band .thought {
  display: block;
  color: var(--on-inverse-3);
}
.cta-side p {
  margin: 0 0 var(--s-6);
  color: var(--on-inverse-2);
}
.cta-band .btn-ghost {
  color: var(--on-inverse);
}
/* The accent ring sits under 3:1 on the inverse band, so focus takes the band's own text color. */
.cta-band :focus-visible {
  outline-color: var(--on-inverse);
}
.cta-band .btn-ghost:hover {
  background: color-mix(in srgb, var(--on-inverse) 10%, transparent);
}

/* ---------- Inner pages ---------- */

.page-hero {
  padding-block: var(--s-8) var(--s-4);
}
.page-hero .breadcrumbs {
  margin-bottom: var(--s-10);
}
.page-hero h1 {
  max-width: 20ch;
  margin: 0;
  font-size: var(--fs-4xl);
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
  overflow-wrap: break-word;
  hyphens: auto;
}
.page-hero h1 .thought {
  display: block;
}
.page-hero .lead {
  max-width: 40rem;
  margin-top: var(--s-6);
}

/* Narrow phones (320-360px): a smaller title and less room around it, so the first thing on the page,
   such as a service's price, is on the first screen above the cookie bar. */
@media (max-width: 360px) {
  .page-hero {
    padding-block: var(--s-4) var(--s-2);
  }
  .page-hero .breadcrumbs {
    margin-bottom: var(--s-4);
  }
  .page-hero h1 {
    font-size: var(--fs-3xl);
  }
  .page-hero .lead {
    margin-top: var(--s-3);
    font-size: var(--fs-md);
  }
  .page-hero + .section {
    padding-top: var(--s-4);
  }
  /* The services list: the first row's summary is cut to two lines (the service page has it whole). */
  .service-row {
    padding-block: var(--s-4);
  }
  .service-summary {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
  }
}

.detail-layout,
.case-detail {
  display: grid;
  gap: var(--s-10);
}
@media (min-width: 960px) {
  .detail-layout,
  .case-detail {
    grid-template-columns: minmax(0, 1fr) 22rem;
    align-items: start;
    gap: var(--s-12);
  }
  .price-card,
  .case-aside {
    position: sticky;
    top: calc(var(--header-h) + var(--s-6));
  }
}
.case-hero-image {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.case-hero-top {
  margin-bottom: var(--s-12);
}
.case-cover {
  margin-bottom: var(--s-12);
}
.detail-back {
  justify-self: start;
}
/* Blog post outline: its h2 sections, the h3 ones indented under them. */
.post-toc ol {
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding-inline-start: var(--s-5);
}
.post-toc-sub {
  margin-inline-start: var(--s-5);
}
/* Hit areas grown without moving anything: a heading link takes half the gap around it, a tag's
   link the whole pill and half the gap around that, so no two areas touch. */
.post-toc a {
  padding-block: calc(var(--s-2) / 2);
}
.chip:has(> a) {
  position: relative;
}
.chip > a::after {
  position: absolute;
  inset: calc(var(--s-2) / -2);
  border-radius: inherit;
  content: "";
}
/* Desktops: the breadcrumbs and the back link are 44px tall to the pointer (phones get it below). */
@media (min-width: 813px) and (min-height: 501px) {
  .breadcrumbs a,
  .detail-back {
    padding-block: calc((2.75rem - 1lh) / 2);
    margin-block: calc((1lh - 2.75rem) / 2);
  }
}
/* A finger needs 44px; on desktop the outline stays a tight list. Each link is a whole row, so a
   heading that wraps to two or three lines grows its target instead of splitting it into short lines. */
@media (pointer: coarse), (max-width: 959px) {
  .post-toc ol {
    gap: 0;
  }
  .post-toc a {
    display: block;
    min-block-size: 2.75rem;
    padding-block: calc((2.75rem - 1lh) / 2);
  }
}
@media (min-width: 960px) {
  .detail-layout,
  .case-detail {
    row-gap: var(--s-8);
  }
  .detail-back {
    grid-column: 1;
  }
  .detail-layout > .price-card,
  .case-detail > .case-aside {
    grid-row: 1 / span 2;
    grid-column: 2;
  }
}

/* A checklist set as ruled rows, for the main points of a page. */
.check-list-lg {
  gap: 0;
  border-top: 1px solid var(--line-strong);
  font-size: var(--fs-lg);
}
.check-list-lg li {
  padding-block: var(--s-4);
  padding-inline-start: var(--s-8);
  border-bottom: 1px solid var(--line);
}
.check-list-lg li::before {
  top: calc(var(--s-4) + 0.4em);
}
.price-card {
  display: grid;
  gap: var(--s-4);
}
/* Three packages share a row from tablets up, never two and one alone. */
.package-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
}
/* Cards of a row are as tall as the tallest: the content stays at the top and the button at the bottom. */
.package-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
.package-card .btn {
  margin-top: auto;
}
.price-card .price,
.package-card .price {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  letter-spacing: var(--tracking-title);
}
.price-card .price small,
.package-card .price small {
  display: block;
  margin-top: var(--s-2);
  color: var(--ink-3);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-regular);
  letter-spacing: 0;
}
/* On tablets three cards are narrow: a lighter frame keeps the price and the button inside. */
@media (min-width: 600px) and (max-width: 959px) {
  .package-card {
    padding: var(--s-5);
  }
  .package-card .price {
    font-size: var(--fs-2xl);
  }
  .package-card .btn {
    padding-inline: var(--s-3);
    white-space: nowrap;
  }
}
.price-card p,
.package-card p {
  margin: 0;
}
.price-card .muted,
.package-card .muted {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-sm);
}
/* The rough equivalent in the second currency reads as part of the price above it. */
.price-card .calc-about {
  margin-block-start: calc(-1 * var(--s-3));
  font-variant-numeric: tabular-nums;
}
.price-card .btn,
.package-card .btn,
.case-aside .btn {
  width: 100%;
}
.service-icon {
  display: inline-grid;
  flex: none;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-sm);
  background: var(--chrome);
  color: var(--ink);
}

.results {
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line-strong);
  list-style: none;
}
.results li {
  padding-block: var(--s-4);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-lg);
}
.case-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: var(--s-4);
}
/* A screenshot presented on a neutral board: wide and tall shots keep one card height. */
.shot {
  display: grid;
  grid-template: minmax(0, 1fr) / minmax(0, 1fr);
  place-items: center;
  aspect-ratio: 4 / 3;
  margin: 0;
  padding: clamp(var(--s-4), 5%, var(--s-8));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--chrome);
  overflow: hidden;
}
.shot:has(figcaption) {
  grid-template: minmax(0, 1fr) auto / minmax(0, 1fr);
  gap: var(--s-3);
}
.shot figcaption {
  color: var(--ink-3);
  font-size: var(--fs-sm);
}
.shot img {
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 100%;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  box-shadow: var(--shadow);
}
.case-tech .chip-list {
  margin-bottom: var(--s-5);
}
.case-quote {
  max-width: 62ch;
  margin: var(--s-10) 0 0;
  padding-inline-start: var(--s-6);
  border-inline-start: 2px solid var(--accent);
  font-size: var(--fs-lg);
  line-height: 1.5;
}
.case-quote footer {
  margin-top: var(--s-3);
  color: var(--ink-3);
  font-size: var(--fs-sm);
}
.case-video {
  width: 100%;
  border-radius: var(--r-lg);
  background: var(--chrome);
}
/* Work filters: chips big enough for a thumb, the chosen one filled. */
.case-filters {
  display: grid;
  gap: var(--s-5);
  margin-bottom: var(--s-10);
}
.case-filter-label {
  margin: 0 0 var(--s-2);
  color: var(--ink-3);
  font-size: var(--fs-sm);
}
.case-filters .chip,
.post-tags .chip {
  min-height: 44px;
  padding-inline: var(--s-4);
  font-size: var(--fs-sm);
  text-decoration: none;
}
.case-filters .chip:hover,
.post-tags .chip:hover {
  border-color: var(--line-strong);
  color: var(--ink);
}
.case-filters .chip[aria-current] {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--surface);
}
.case-aside {
  display: grid;
  gap: var(--s-6);
}
.case-aside dl {
  margin: 0;
}
.case-aside dl > div {
  padding-block: var(--s-3);
  border-bottom: 1px solid var(--line);
}
.case-aside dl > div:first-child {
  padding-top: 0;
}
.case-aside dt {
  margin-bottom: var(--s-1);
  color: var(--ink-3);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
.case-aside dd {
  margin: 0;
}

.contact-layout {
  display: grid;
  gap: var(--s-12);
}
@media (min-width: 960px) {
  .contact-layout {
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    align-items: start;
  }
}
@media (pointer: coarse) {
  .section-title a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}
.contact-form {
  display: grid;
  gap: var(--s-5);
}
.contact-form > .btn {
  justify-self: start;
}
.form-row {
  display: grid;
  gap: var(--s-5);
}
@media (min-width: 640px) {
  .form-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.form-note {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  font-size: var(--fs-sm);
}
.hp-field {
  position: absolute;
  inset-inline-start: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.contact-channels {
  display: grid;
  gap: var(--s-3);
}
.contact-aside-title {
  margin: 0 0 var(--s-2);
  font-size: var(--fs-xl);
}
.channel {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--ink);
  font-weight: var(--fw-medium);
  text-decoration: none;
  overflow-wrap: anywhere;
  transition: border-color var(--dur-1) var(--ease);
}
a.channel:hover {
  border-color: var(--line-strong);
}
.channel > span:nth-child(2) {
  flex: 1;
  min-width: 0;
}
.channel-go {
  color: var(--ink-3);
  transition: color var(--dur-1) var(--ease), translate var(--dur-2) var(--ease-out);
}
a.channel:hover .channel-go {
  color: var(--ink);
  translate: calc(2px * var(--dir)) -2px;
}
.socials:empty {
  display: none;
}
/* Channels grouped into one card with hairline rows. */
.channel-list {
  display: grid;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.channel-list .channel {
  border: 0;
  border-radius: 0;
  background: none;
  transition: background-color var(--dur-1) var(--ease);
}
.channel-list .channel + .channel {
  border-top: 1px solid var(--line);
}
.channel-list a.channel:hover {
  background: var(--chrome);
}
.channel small {
  display: block;
  color: var(--ink-3);
  font-size: var(--fs-xs);
  font-weight: var(--fw-regular);
}
.requisites-card {
  display: grid;
  gap: var(--s-1);
  margin-top: var(--s-3);
  padding: var(--s-5);
  font-size: var(--fs-sm);
}

.thanks {
  display: grid;
  justify-items: start;
  gap: var(--s-5);
  padding-bottom: var(--s-6);
}
.thanks > .steps {
  justify-self: stretch;
}
.thanks-next {
  margin: var(--s-12) 0 var(--s-4);
  font-size: var(--fs-2xl);
}
.thanks h1 {
  margin: 0;
  font-size: var(--fs-4xl);
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
}
.thanks .lead {
  max-width: 40rem;
  margin: 0;
}
.thanks-icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--success-soft);
  color: var(--success);
}

.empty-state {
  padding: var(--s-10) var(--s-8);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
  color: var(--ink-2);
}

/* Long-form documents: one reading column, contents on the side from 1100px. */
.doc-layout {
  display: grid;
  gap: var(--s-8);
  align-items: start;
}
@media (min-width: 1100px) {
  /* The text column is as wide as its measure, and the contents follow it, not the far edge. */
  .doc-layout {
    grid-template-columns: minmax(0, max-content) 16rem;
    justify-content: start;
    gap: var(--s-12);
  }
  .doc-toc {
    grid-column: 2;
    grid-row: 1;
    position: sticky;
    top: calc(var(--header-h) + var(--s-6));
  }
}
.doc-toc {
  padding: var(--s-5) var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  font-size: var(--fs-sm);
}
.doc-toc-title {
  margin: 0 0 var(--s-3);
  color: var(--ink-3);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
.doc-toc ol {
  display: grid;
  gap: var(--s-1);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: toc;
}
.doc-toc li {
  counter-increment: toc;
}
.doc-toc a {
  display: flex;
  gap: var(--s-3);
  padding-block: var(--s-1);
  color: var(--ink-2);
  text-decoration: none;
  transition: color var(--dur-1) var(--ease);
}
@media (pointer: coarse) {
  .doc-toc a {
    align-items: center;
    min-height: 44px;
  }
}
.doc-toc a::before {
  content: counter(toc, decimal-leading-zero);
  flex: none;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.doc-toc a:hover,
.doc-toc a[aria-current] {
  color: var(--ink);
}
.doc-toc a[aria-current] {
  font-weight: var(--fw-medium);
}
.doc-meta {
  margin: 0 0 var(--s-8);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--line);
  color: var(--ink-3);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.doc-main {
  min-width: 0;
  max-width: 68ch;
}
.doc-body {
  font-size: var(--fs-lg);
  line-height: 1.65;
}
.doc-body > :first-child {
  margin-top: 0;
}
.doc-body h2,
.doc-body h3 {
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-title);
  text-wrap: balance;
  scroll-margin-top: calc(var(--header-h) + var(--s-6));
}
.doc-body h2 {
  margin-top: var(--s-8);
  padding-top: var(--s-8);
  border-top: 1px solid var(--line);
}
.doc-body > h2:first-child {
  padding-top: 0;
  border-top: 0;
}
.doc-body ul > li::marker {
  color: var(--ink-3);
}
.doc-body ol > li::marker {
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.doc-body table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  line-height: 1.5;
}
.doc-body th {
  color: var(--ink);
  font-weight: var(--fw-semibold);
  border-bottom-color: var(--line-strong);
  white-space: nowrap;
}
.doc-body td {
  vertical-align: top;
}

/* ---------- Error pages ---------- */

.error-main {
  display: grid;
  justify-items: start;
  gap: var(--s-4);
  padding-block: var(--s-10) var(--s-12);
}
.error-num {
  margin: 0;
  color: var(--ink-3);
  font-family: var(--font-display);
  font-size: calc(var(--fs-4xl) * 1.6);
  font-variant-numeric: tabular-nums;
  font-weight: var(--fw-semibold);
  line-height: 0.9;
  letter-spacing: var(--tracking-display);
}
.error-main h1 {
  margin: 0;
  font-size: var(--fs-3xl);
}
.error-main .lead {
  max-width: 40ch;
  margin: 0;
}
.error-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin: var(--s-4) 0 0;
}
.error-search {
  width: min(100%, 30rem);
}
.error-search .cluster {
  flex-wrap: nowrap;
}
.error-search .btn {
  flex: none;
}
.error-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s-6);
  margin: 0;
}
.error-links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 2.75rem;
  min-inline-size: 2.75rem;
  color: var(--ink-2);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 0.25em;
}
.error-links a:hover {
  color: var(--ink);
  text-decoration-color: currentColor;
}
.error-langs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--s-4);
  margin-top: var(--s-6);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  color: var(--ink-3);
  font-size: var(--fs-sm);
}
.error-langs a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--ink-2);
}

/* Touch targets: on phones, tablets and phones on their side every standalone link is at least 44px tall. */
@media (max-width: 812px), (max-height: 500px), (pointer: coarse) {
  .footer-grid a,
  .footer-bottom a,
  .footer-langs a,
  .breadcrumbs a,
  .more-link,
  .doc-toc a {
    display: inline-flex;
    align-items: center;
    min-width: 2.75rem;
    min-height: 2.75rem;
  }
  .footer-grid ul {
    gap: 0;
  }
  /* A touch tablet shows the full header: its links, arrows and the language button get 44px too. */
  .main-nav > ul > li > a {
    padding-block: calc((2.75rem - 1lh) / 2);
  }
  .main-nav .menu > summary {
    width: 2.75rem;
    height: 2.75rem;
  }
  .site-header .btn-sm {
    --btn-h: 2.75rem;
  }
  .skip-link {
    display: flex;
    align-items: center;
    min-height: 2.75rem;
  }
  /* A link inside a line of text: vertical padding of an inline box grows its hit box, not the line. */
  .checkbox-row a,
  .field-hint a {
    padding-block: calc((2.75rem - 1em) / 2);
  }
  .case-aside dd a {
    padding-block: calc((2.75rem - 1lh) / 2);
    margin-block: calc((1lh - 2.75rem) / 2);
  }
  /* A one-line consent label gets a 44px row without moving the form. */
  .checkbox-row {
    padding-block: 0.6875rem;
    margin-block: -0.6875rem;
  }
  .header-cta {
    --btn-h: 2.75rem;
  }
}

/* Phones on their side: a lower header and tighter page tops, so the hero's buttons and a
   service's price are on the first screen above the cookie bar. */
@media (max-height: 500px) and (orientation: landscape) {
  :root {
    --header-h: 3.25rem;
  }
  .hero {
    padding-block: var(--s-3) var(--s-10);
  }
  .hero .eyebrow {
    margin-bottom: var(--s-2);
  }
  .hero-title {
    max-width: none;
    font-size: var(--fs-2xl);
  }
  .hero-aside {
    gap: var(--s-3);
    margin-top: var(--s-4);
  }
  .hero-aside .lead,
  .page-hero .lead {
    max-width: none;
    font-size: var(--fs-md);
  }
  .page-hero {
    padding-block: 0;
  }
  .page-hero .breadcrumbs {
    margin-bottom: 0;
  }
  .page-hero h1 {
    max-width: none;
    font-size: var(--fs-3xl);
  }
  .page-hero .lead {
    margin-top: var(--s-2);
  }
  .page-hero + .section {
    padding-top: var(--s-4);
  }
  .detail-layout > .price-card {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--s-2) var(--s-5);
    padding: var(--s-4) var(--s-5);
  }
  .price-card .btn {
    grid-area: 1 / 2 / span 2;
    width: auto;
  }
  .price-card .btn ~ .muted {
    grid-column: 1 / -1;
  }
  .price-card .price {
    font-size: var(--fs-2xl);
  }
  .price-card .price small {
    display: inline;
    margin: 0;
  }
  .price-card .service-icon {
    display: none;
  }
}
/* The lowest of them (568x320) need a smaller title and lead to fit the hero's buttons and the order button too. */
@media (max-height: 340px) and (orientation: landscape) {
  .hero {
    padding-top: var(--s-1);
  }
  .hero .eyebrow {
    margin-bottom: var(--s-1);
  }
  .hero-title {
    font-size: var(--fs-xl);
  }
  .hero-aside {
    gap: var(--s-2);
    margin-top: var(--s-2);
  }
  .hero-aside .lead {
    font-size: var(--fs-sm);
    line-height: var(--lh-snug);
  }
  .page-hero h1 {
    font-size: var(--fs-2xl);
  }
  .page-hero .lead {
    margin-top: var(--s-1);
    font-size: var(--fs-sm);
  }
  .page-hero + .section {
    padding-top: var(--s-1);
  }
  .detail-layout > .price-card {
    padding-block: var(--s-3);
  }
  .price-card .btn {
    align-self: start;
  }
}

/* ---------- Cookie banner ---------- */

.cookie-banner {
  position: fixed;
  bottom: var(--gutter);
  inset-inline-start: var(--gutter);
  z-index: var(--z-banner);
  display: grid;
  gap: var(--s-3);
  width: min(400px, calc(100vw - 2 * var(--gutter)));
  max-height: calc(100dvh - 2 * var(--gutter));
  overflow-y: auto;
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow);
  font-size: var(--fs-sm);
  animation: rise var(--dur-3) var(--ease-out);
}
.cookie-banner[hidden] {
  display: none;
}
.cookie-banner h2 {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  font-size: var(--fs-md);
  letter-spacing: var(--tracking-snug);
}
.cookie-banner p {
  margin: 0;
  color: var(--ink-2);
}
.cookie-options {
  display: grid;
  gap: var(--s-3);
}
.cookie-options[hidden] {
  display: none;
}
.cookie-option {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--s-1) var(--s-4);
  padding-block: var(--s-3);
  border-top: 1px solid var(--line);
}
.cookie-option small {
  grid-column: 1 / -1;
  color: var(--ink-3);
  font-size: var(--fs-xs);
}
/* Every control in the banner is a full 44px touch target, on tablets too. */
.cookie-banner .btn-sm {
  --btn-h: 2.75rem;
  padding-inline: var(--s-3);
}
.cookie-banner .cookie-policy {
  justify-self: start;
  min-block-size: 2.75rem;
  padding-inline: 0;
  white-space: nowrap;
}
.cookie-option .switch {
  min-height: 2.75rem;
  align-items: center;
}
.cookie-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-2);
}

/* A bar along the bottom edge on every screen, one line where the width allows (two lines
   of text over the buttons on phones, so a form's button and the price on the first screen stay clear);
   "customize" is an icon there and opens the full card with the whole text and the policy link. The page
   gets room below so the bar never sits over the last control. It stays put while the visitor
   types: showing it again on blur moved the button under the finger and the tap was lost. */
.cookie-banner:not(:has(.cookie-options:not([hidden]))) {
  inset-inline-end: 0;
  bottom: 0;
  inset-inline-start: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) var(--s-3);
  width: auto;
  padding: var(--s-2) max(var(--gutter), env(safe-area-inset-right)) max(var(--s-2), env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left)); /* physical: the screen's cut-outs are physical sides */
  border-width: 1px 0 0;
  border-radius: 0;
  overflow: visible;
  animation-name: fade-in;
}
.cookie-banner:not(:has(.cookie-options:not([hidden]))) h2,
.cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-customize span {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.cookie-banner:not(:has(.cookie-options:not([hidden]))) p {
  display: -webkit-box;
  flex: 1 1 0;
  min-inline-size: 0;
  overflow: hidden;
  font-size: var(--fs-xs);
  line-height: 1.3;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
/* The policy link sits outside the cut text, so it is never cut and stays a full 44px target. */
.cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-policy {
  flex: 0 0 auto;
  font-size: var(--fs-xs);
}
/* Short of a desktop the link folds to two lines inside its 44px, leaving the text more width. */
@media (max-width: 959px) {
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-policy {
    max-inline-size: 5.5rem;
    line-height: 1.2;
    text-align: start;
    white-space: normal;
  }
}
.cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-actions {
  flex: 1 1 auto;
  gap: var(--s-2);
  margin: 0;
}
/* Each label stays on one line; a button that no longer fits moves to its own row. */
.cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-actions .btn:not(.cookie-customize) {
  flex: 1 0 auto;
  padding-inline: var(--s-3);
  white-space: nowrap;
}
/* The narrowest phones: both labels wrap inside one row of buttons rather than adding a row. */
@media (max-width: 374px) {
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-actions .btn:not(.cookie-customize) {
    flex: 1 1 0;
    line-height: 1.15;
    white-space: normal;
  }
}
/* Phones: the two lines of text share a row with the policy link, the buttons take the row below. */
@media (max-width: 599px) {
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) {
    row-gap: 0; /* the link's 44px row already leaves air above the buttons */
  }
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-actions {
    flex-basis: 100%;
  }
}
.cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-customize {
  order: -1;
  width: 2.75rem;
  padding: 0;
}
.cookie-banner:has(.cookie-options:not([hidden])) {
  inset-inline-start: max(var(--gutter), env(safe-area-inset-left));
  bottom: max(var(--gutter), env(safe-area-inset-bottom));
  width: min(400px, calc(100vw - 2 * var(--gutter)));
}
/* The bar's height while it is open: an estimate here, its real height once site.js measures it. Everything
   that keeps clear of the bar (the page's room below, the cabinet's bottom bar, toasts) reads it, so without
   scripts nothing slides under the bar either. */
:root:has(.cookie-banner:not([hidden])) {
  --banner-h: calc(7rem + env(safe-area-inset-bottom));
  scroll-padding-bottom: calc(var(--banner-h) + var(--s-2));
}
@media (min-width: 600px), (max-height: 500px) {
  :root:has(.cookie-banner:not([hidden])) {
    --banner-h: calc(4.5rem + env(safe-area-inset-bottom));
  }
}
body:has(.cookie-banner:not([hidden])) {
  padding-bottom: var(--banner-h);
}
body:has(.cookie-banner:not([hidden]) .cookie-options:not([hidden])) {
  padding-bottom: calc(var(--banner-h) + max(var(--gutter), env(safe-area-inset-bottom)));
}
/* On a tall phone the service's order button rides above the open bar while its card is on screen; on a
   shorter one it would ride up over the price, so it stays in place there. */
@media (max-width: 959px) and (min-height: 800px) {
  :root:has(.cookie-banner:not([hidden])) .detail-layout > .price-card .btn-primary {
    position: sticky;
    bottom: calc(var(--banner-h) + var(--s-2));
  }
}
/* Desktops: the whole text on the left, the buttons at their natural width on the right. */
@media (min-width: 960px) and (min-height: 501px) {
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) {
    flex-wrap: nowrap;
    gap: var(--s-6);
    padding-block: var(--s-3) max(var(--s-3), env(safe-area-inset-bottom));
  }
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) p {
    display: block;
    flex: 1 1 auto;
    overflow: visible;
    font-size: var(--fs-sm);
  }
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-actions {
    flex: 0 0 auto;
  }
}
/* Phones on their side: one thin row, the text cut to a line beside the buttons on the right. */
@media (max-height: 500px) and (orientation: landscape) {
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) {
    flex-wrap: nowrap;
  }
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) p {
    display: block;
    flex: 1 1 0;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .cookie-banner:not(:has(.cookie-options:not([hidden]))) .cookie-actions {
    flex: 0 0 auto;
  }
}

/* Phones: the price card's order button moves to the bottom of the screen, where it rides over the
   service's text above the cookie bar (its height comes from --banner-h, with or without scripts)
   and settles back in place at the end of the text. */
.order-bar {
  display: none;
}
@media (max-width: 599px) {
  :root {
    --order-bar-h: var(--control-h);
  }
  .price-card .btn {
    display: none;
  }
  .order-bar {
    --btn-h: var(--order-bar-h);
    position: sticky;
    bottom: calc(var(--banner-h, 0px) + max(var(--s-3), env(safe-area-inset-bottom)));
    z-index: 1;
    display: flex;
    box-shadow: var(--shadow);
  }
  :root:has(.cookie-options:not([hidden])) .order-bar {
    bottom: calc(var(--banner-h, 0px) + max(var(--gutter), env(safe-area-inset-bottom)) + var(--s-3));
  }
  /* A control reached with Tab stops above the button, not under it. */
  :root:has(.detail-layout > .order-bar) {
    scroll-padding-bottom: calc(var(--banner-h, 0px) + var(--order-bar-h) + var(--s-6));
  }
}

/* ---------- Staff edit ---------- */

/* Signed-in staff only: one floating button bottom right, kept above the cookie bar. With
   the site script it toggles edit mode, which shows a pencil on every block; without it, it links
   to the admin page of this page and the pencils stay hidden. */
.staff-edit {
  --staff-lift: 0px;
  position: fixed;
  inset-inline-end: max(var(--gutter), env(safe-area-inset-right));
  bottom: calc(max(var(--gutter), env(safe-area-inset-bottom)) + var(--staff-lift));
  z-index: var(--z-banner);
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 44px;
  padding: 0 var(--s-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--ink);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
/* Phones: a round icon, so it covers as little of the page as it can; the label stays for screen readers. */
@media (max-width: 599px) {
  .staff-edit {
    justify-content: center;
    inline-size: 44px;
    padding: 0;
  }
  .staff-edit span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
.staff-edit:hover {
  border-color: var(--ink-3);
}
.staff-edit[aria-pressed="true"] {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
}
.staff-edit:focus-visible,
.staff-pencil:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.staff-pencil {
  display: none;
}
.staff-editing .staff-pencil {
  position: absolute;
  top: var(--s-4);
  inset-inline-end: max(var(--gutter), env(safe-area-inset-right));
  z-index: 1;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--accent);
  border-radius: var(--r-pill);
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--accent-ink);
}
.staff-editing .staff-pencil:hover {
  background: var(--accent);
  color: var(--on-accent);
}
.staff-editing :has(> .staff-pencil) {
  position: relative;
  outline: 1px dashed var(--line-strong);
  outline-offset: -1px;
}
.staff-editing :has(> .staff-pencil:is(:hover, :focus-visible)) {
  outline-color: var(--accent);
}
:root:has(.cookie-banner:not([hidden])) .staff-edit {
  --staff-lift: calc(var(--banner-h) + var(--s-2));
}
@media (max-width: 959px), (max-height: 500px) {
  /* The cookie card with its options open takes the whole phone width; the button waits. */
  body:has(.cookie-options:not([hidden])) .staff-edit {
    display: none;
  }
}
/* Phones on a service page: the button rides over the order bar, which rides over the cookie bar. */
@media (max-width: 599px) {
  :root:has(.detail-layout > .order-bar) .staff-edit {
    --staff-lift: calc(var(--banner-h, 0px) + var(--order-bar-h) + var(--s-3));
  }
}

/* A draft staff open at its address on the site: a strip over the page says only they see it. */
.draft-bar {
  margin: 0;
  padding-block: var(--s-3);
  padding-inline: var(--gutter);
  border-block-end: 1px solid color-mix(in oklab, var(--warning) 30%, var(--line));
  background: var(--warning-soft);
  color: var(--ink);
  font-size: var(--fs-sm);
  text-align: center;
}
.draft-bar b {
  color: var(--warning);
  font-weight: var(--fw-semibold);
}

/* ---------- Motion and preview ---------- */

.will-reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out);
}
.will-reveal.is-visible {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .will-reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .site-menu[open],
  .site-menu[open]::backdrop,
  .cookie-banner {
    animation: none;
  }
}

/* The admin sizes a stacked preview frame to its page, so the page must not stretch to the frame. */
body.is-preview {
  min-height: 0;
}

.is-preview a,
.is-preview button,
.is-preview summary {
  pointer-events: none;
}
.case-aside dd a {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
}

@media print {
  :root {
    color-scheme: light;
  }

  .site-header,
  .site-footer,
  .skip-link,
  .offer-actions {
    display: none !important;
  }

  .will-reveal {
    opacity: 1;
    transform: none;
  }
}

