/* ==========================================================================
   kvyk.css — the kvyk.ai design system
   --------------------------------------------------------------------------
   A single, framework-free stylesheet. No Tailwind, no build step.
   Drop it into any page with:  <link rel="stylesheet" href="kvyk.css">

   Contents
     1. Fonts          — self-hosted @font-face (Inter, JetBrains Mono, Source Serif 4)
     2. Tokens         — :root design variables (color, space, type, etc.)
     3. Reset & base   — minimal normalize + sensible element defaults
     4. Typography     — .kvyk-display / headline / body / label / overline
     5. Layout         — container, stack, cluster, grid, app-shell, surfaces
     6. Components      — buttons, fields, cards, nav, chat, stepper, …
     7. Utilities       — a small, deliberate helper set (not a framework)

   Conventions
     • Tokens are CSS custom properties prefixed  --kvyk-*
     • Components use a  kvyk-  prefix with BEM-style modifiers:
         block        .kvyk-btn
         element      .kvyk-card__header
         variant      .kvyk-btn--accent
         state        .is-active / [aria-current] / [disabled] / [aria-invalid]
     • Component colors are driven by local --_* vars so variants only
       re-map a few values instead of re-declaring every rule.
   ========================================================================== */

/* ==========================================================================
   1. FONTS
   ========================================================================== */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/Inter-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/Inter-Medium.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/Inter-SemiBold.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/Inter-Bold.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url("fonts/Inter-Black.woff2") format("woff2");
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/JetBrainsMono-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/JetBrainsMono-Medium.woff2") format("woff2");
}
@font-face {
  font-family: "Source Serif 4";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/SourceSerif4-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "Source Serif 4";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/SourceSerif4-It.woff2") format("woff2");
}
@font-face {
  font-family: "Source Serif 4";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/SourceSerif4-Bold.woff2") format("woff2");
}
@font-face {
  font-family: "Source Serif 4";
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/SourceSerif4-BoldIt.woff2") format("woff2");
}

/* ==========================================================================
   2. TOKENS
   --------------------------------------------------------------------------
   The single source of truth. Everything below references these. Re-theming
   = override these variables (e.g. on a [data-theme] or a scoped container).
   ========================================================================== */
:root {
  color-scheme: light;

  /* ---- Brand --------------------------------------------------------- */
  --kvyk-brand-mark: #3b82f6;          /* logo triangle only */

  /* ---- Primary (near-black, the strong CTA / brand text) ------------- */
  --kvyk-primary: #000000;
  --kvyk-on-primary: #ffffff;
  --kvyk-primary-container: #131b2e;
  --kvyk-on-primary-container: #7c839b;
  --kvyk-primary-fixed: #dae2fd;
  --kvyk-primary-fixed-dim: #bec6e0;
  --kvyk-on-primary-fixed: #131b2e;
  --kvyk-on-primary-fixed-variant: #3f465c;

  /* ---- Secondary (electric blue — the action / accent color) --------- */
  --kvyk-secondary: #0058be;
  --kvyk-on-secondary: #ffffff;
  --kvyk-secondary-container: #2170e4;
  --kvyk-on-secondary-container: #fefcff;
  --kvyk-secondary-fixed: #d8e2ff;
  --kvyk-secondary-fixed-dim: #adc6ff;
  --kvyk-on-secondary-fixed: #001a42;
  --kvyk-on-secondary-fixed-variant: #004395;

  /* ---- Tertiary (mint green — positive / success accents) ------------ */
  --kvyk-tertiary: #000000;
  --kvyk-tertiary-container: #002113;
  --kvyk-on-tertiary-container: #009668;
  --kvyk-tertiary-fixed: #6ffbbe;
  --kvyk-tertiary-fixed-dim: #4edea3;
  --kvyk-on-tertiary-fixed: #002113;
  --kvyk-on-tertiary-fixed-variant: #005236;

  /* ---- Error --------------------------------------------------------- */
  --kvyk-error: #ba1a1a;
  --kvyk-on-error: #ffffff;
  --kvyk-error-container: #ffdad6;
  --kvyk-on-error-container: #93000a;

  /* ---- Surfaces & background (blue-tinted neutrals) ------------------ */
  --kvyk-background: #f8f9ff;
  --kvyk-on-background: #0b1c30;
  --kvyk-surface: #f8f9ff;
  --kvyk-surface-bright: #f8f9ff;
  --kvyk-surface-dim: #cbdbf5;
  --kvyk-surface-container-lowest: #ffffff;
  --kvyk-surface-container-low: #eff4ff;
  --kvyk-surface-container: #e5eeff;
  --kvyk-surface-container-high: #dce9ff;
  --kvyk-surface-container-highest: #d3e4fe;
  --kvyk-surface-variant: #d3e4fe;
  --kvyk-on-surface: #0b1c30;
  --kvyk-on-surface-variant: #45464d;

  /* ---- Lines --------------------------------------------------------- */
  --kvyk-outline: #76777d;
  --kvyk-outline-variant: #c6c6cd;

  /* ---- Inverse (dark accents on a light UI) -------------------------- */
  --kvyk-inverse-surface: #213145;
  --kvyk-inverse-on-surface: #eaf1ff;
  --kvyk-inverse-primary: #bec6e0;
  --kvyk-surface-tint: #565e74;

  /* ---- Semantic aliases (ergonomic shortcuts) ------------------------ */
  --kvyk-text: var(--kvyk-on-surface);
  --kvyk-text-muted: var(--kvyk-on-surface-variant);
  --kvyk-border: var(--kvyk-outline-variant);
  --kvyk-accent: var(--kvyk-secondary);
  /* Links in running text, and the filled accent button under the pointer:
     their own tokens, so a page that sets its own accent (an organisation's
     colour) can keep its links readable on the surfaces they sit on. */
  --kvyk-link: var(--kvyk-secondary);
  --kvyk-secondary-hover: var(--kvyk-on-secondary-fixed-variant);
  /* A row or item under the pointer, and the one that is selected or open:
     the two palest steps of the neutral ramp (blue-tinted, as every neutral
     here is), so the accent blue stays for links, focus and the main action. */
  --kvyk-surface-hover: var(--kvyk-background);
  --kvyk-surface-selected: var(--kvyk-surface-container-low);
  /* A table's every other row, and the row under the pointer, a step darker
     (#225): see-through, so the shade of a table that scrolls sideways still
     shows on them. Over white they come to about #f1f6ff and #deebfe, where
     body and muted text both keep well over 4.5:1. */
  --kvyk-table-stripe: color-mix(in srgb, var(--kvyk-surface-container) 55%, transparent);
  --kvyk-table-hover: color-mix(in srgb, var(--kvyk-surface-container-highest) 75%, transparent);
  /* The shade at the edge of a table that scrolls sideways. */
  --kvyk-scroll-shadow: rgba(15, 23, 42, 0.14);

  /* ---- Typography ---------------------------------------------------- */
  --kvyk-font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --kvyk-font-mono: "JetBrains Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  --kvyk-weight-regular: 400;
  --kvyk-weight-medium: 500;
  --kvyk-weight-semibold: 600;
  --kvyk-weight-bold: 700;
  --kvyk-weight-black: 900;

  /* Line height: one for running text at every size, a tighter one for
     every heading. Labels, badges, buttons and table cells keep their own
     fixed lines, so the compact UI does not grow with them. */
  --kvyk-leading-body: 1.6;
  --kvyk-leading-heading: 1.25;

  /* ---- Spacing (4px base grid) --------------------------------------- */
  --kvyk-space-2xs: 2px;
  --kvyk-space-xs: 4px;
  --kvyk-space-sm: 8px;
  --kvyk-space-sm-md: 12px;
  --kvyk-space-md: 16px;
  --kvyk-space-lg: 24px;
  --kvyk-space-xl: 32px;
  --kvyk-space-2xl: 48px;
  --kvyk-space-3xl: 64px;
  /* Text after text: between paragraphs (or a paragraph and a list), and
     between a title and the line under it. */
  --kvyk-space-paragraph: var(--kvyk-space-md);
  --kvyk-space-lead: var(--kvyk-space-sm-md);
  --kvyk-gutter: 24px;
  --kvyk-margin-mobile: 16px;
  --kvyk-margin-desktop: 40px;

  /* ---- Radius (crisp, precise — small by design) --------------------- */
  --kvyk-radius-xs: 2px;
  --kvyk-radius-sm: 4px;
  --kvyk-radius-md: 8px;
  --kvyk-radius-lg: 12px;
  --kvyk-radius-xl: 16px;
  --kvyk-radius-pill: 999px;
  /* Cards and other framed blocks (tables, lists, empty states, option
     panels) are square-cornered rectangles, set apart by space. */
  --kvyk-radius-card: 0;
  --kvyk-radius-circle: 50%;

  /* ---- Elevation (soft slate shadows; light UI = restrained depth) --- */
  --kvyk-elevation-1: 0 1px 2px rgba(15, 23, 42, 0.04);
  --kvyk-elevation-2: 0 4px 12px rgba(15, 23, 42, 0.05);
  --kvyk-elevation-3: 0 12px 32px rgba(15, 23, 42, 0.10);
  --kvyk-elevation-accent: 0 4px 12px rgba(0, 88, 190, 0.20);
  --kvyk-elevation-accent-hover: 0 12px 32px rgba(0, 88, 190, 0.30);
  --kvyk-scrim: rgba(15, 23, 42, 0.32);

  /* ---- Focus ring ---------------------------------------------------- */
  --kvyk-ring-color: rgba(0, 88, 190, 0.35);
  --kvyk-ring: 0 0 0 3px var(--kvyk-ring-color);

  /* ---- Motion -------------------------------------------------------- */
  --kvyk-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --kvyk-duration-fast: 120ms;
  --kvyk-duration: 200ms;
  --kvyk-duration-slow: 320ms;

  /* ---- Layout -------------------------------------------------------- */
  --kvyk-max-width: 1440px;
  --kvyk-sidebar-width: 256px;
  --kvyk-sidebar-width-collapsed: 64px;
  --kvyk-header-height: 64px;
  --kvyk-askbar-height: 53px;
  --kvyk-control-height: 40px;
  --kvyk-control-height-sm: 32px;
  /* The longest comfortable line of running text. */
  --kvyk-measure: 48rem;

  /* ---- Z-index ------------------------------------------------------- */
  --kvyk-z-base: 1;
  --kvyk-z-header: 30;
  --kvyk-z-nav: 40;
  --kvyk-z-overlay: 50;
  --kvyk-z-tooltip: 60;
  --kvyk-z-toast: 70;
}

/* Dark, where the device asks for it, on a page that opts in with
   <html data-theme="device"> (the pages before an app opens: its sign-in, a
   shared device's screen). Elsewhere the light theme above is the only one.
   Only colour tokens change; the fixed accent washes stay as they are. */
@media (prefers-color-scheme: dark) {
  :root[data-theme="device"] {
    color-scheme: dark;

    --kvyk-primary: #e3ebfa;
    --kvyk-on-primary: #0b1c30;
    --kvyk-primary-container: #d3e4fe;
    --kvyk-on-primary-container: #3f465c;

    --kvyk-secondary: #adc6ff;
    --kvyk-on-secondary: #002e69;
    --kvyk-secondary-container: #004395;
    --kvyk-on-secondary-container: #d8e2ff;
    --kvyk-secondary-hover: #d8e2ff;

    --kvyk-error: #ffb4ab;
    --kvyk-on-error: #690005;
    --kvyk-error-container: #5a1414;
    --kvyk-on-error-container: #ffdad6;

    --kvyk-background: #0b1424;
    --kvyk-on-background: #dce6f7;
    --kvyk-surface: #0b1424;
    --kvyk-surface-bright: #2a3548;
    --kvyk-surface-dim: #0b1424;
    --kvyk-surface-container-lowest: #121c2e;
    --kvyk-surface-container-low: #172235;
    --kvyk-surface-container: #1c283c;
    --kvyk-surface-container-high: #243044;
    --kvyk-surface-container-highest: #2c394f;
    --kvyk-surface-variant: #2c394f;
    --kvyk-on-surface: #e3ebfa;
    --kvyk-on-surface-variant: #b4bccc;

    --kvyk-outline: #8c94a3;
    --kvyk-outline-variant: #364154;

    --kvyk-inverse-surface: #c6d3ea;
    --kvyk-inverse-on-surface: #213145;
    --kvyk-inverse-primary: #0058be;
    --kvyk-surface-tint: #bec6e0;

    /* A card is lighter than the page behind it, so what is under the
       pointer or chosen is lighter still. */
    --kvyk-surface-hover: var(--kvyk-surface-container-low);
    --kvyk-surface-selected: var(--kvyk-surface-container);
    --kvyk-scroll-shadow: rgba(0, 0, 0, 0.4);

    --kvyk-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.3);
    --kvyk-elevation-2: 0 4px 12px rgba(0, 0, 0, 0.35);
    --kvyk-elevation-3: 0 12px 32px rgba(0, 0, 0, 0.45);
    --kvyk-elevation-accent: 0 4px 12px rgba(173, 198, 255, 0.2);
    --kvyk-elevation-accent-hover: 0 12px 32px rgba(173, 198, 255, 0.3);
    --kvyk-scrim: rgba(0, 0, 0, 0.55);
    --kvyk-ring-color: rgba(173, 198, 255, 0.45);
  }
}

/* ==========================================================================
   3. RESET & BASE
   ========================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

/* The hidden attribute always hides. Components set their own display (flex,
   grid, …), which would otherwise beat the browser's [hidden] rule and show
   what a page marked hidden, such as a form's success message before submit. */
[hidden] {
  display: none !important;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  tab-size: 4;
}

body {
  font-family: var(--kvyk-font-sans);
  font-size: 16px;
  line-height: 1.5;
  font-weight: var(--kvyk-weight-regular);
  color: var(--kvyk-on-background);
  background-color: var(--kvyk-background);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img,
picture,
svg,
video,
canvas {
  display: block;
  max-width: 100%;
}

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

button {
  background: none;
  border: none;
  cursor: pointer;
}

a {
  color: var(--kvyk-link);
  text-decoration: none;
  transition: color var(--kvyk-duration) var(--kvyk-ease);
}
a:hover {
  text-decoration: underline;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-semibold);
  line-height: var(--kvyk-leading-heading);
  color: var(--kvyk-on-surface);
  text-wrap: balance;
}
h1 { font-size: 32px; letter-spacing: -0.01em; }
h2 { font-size: 24px; }
h3 { font-size: 20px; }
h4 { font-size: 16px; }

p { line-height: var(--kvyk-leading-body); }

hr {
  border: none;
  border-top: 1px solid var(--kvyk-outline-variant);
}

code, kbd, samp, pre {
  font-family: var(--kvyk-font-mono);
  font-size: 0.9em;
}

::selection {
  background: var(--kvyk-secondary-container);
  color: var(--kvyk-on-secondary-container);
}

:focus-visible {
  outline: none;
  box-shadow: var(--kvyk-ring);
  border-radius: var(--kvyk-radius-xs);
}

/* Thin, unobtrusive scrollbars (matches the "precise" tone) */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--kvyk-outline-variant) transparent;
}
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background-color: var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-pill);
  border: 2px solid transparent;
  background-clip: content-box;
}

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

/* ==========================================================================
   4. TYPOGRAPHY
   --------------------------------------------------------------------------
   Inter for prose and headings. JetBrains Mono for labels, metadata and UI
   chrome — the mono is a deliberate signature, not decoration.
   ========================================================================== */
.kvyk-display-lg {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-bold);
  font-size: 48px;
  line-height: var(--kvyk-leading-heading);
  letter-spacing: -0.02em;
}
.kvyk-headline-lg {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-semibold);
  font-size: 32px;
  line-height: var(--kvyk-leading-heading);
  letter-spacing: -0.01em;
}
.kvyk-headline-md {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-semibold);
  font-size: 24px;
  line-height: var(--kvyk-leading-heading);
}
.kvyk-title {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-semibold);
  font-size: 20px;
  line-height: var(--kvyk-leading-heading);
}
.kvyk-body-lg {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-regular);
  font-size: 18px;
  line-height: 28px;
}
.kvyk-body-md {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-regular);
  font-size: 16px;
  line-height: 24px;
}
.kvyk-body-sm {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-regular);
  font-size: 14px;
  line-height: 20px;
}
.kvyk-label-md {
  font-family: var(--kvyk-font-mono);
  font-weight: var(--kvyk-weight-medium);
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0.02em;
}
.kvyk-label-sm {
  font-family: var(--kvyk-font-mono);
  font-weight: var(--kvyk-weight-medium);
  font-size: 12px;
  line-height: 16px;
}
.kvyk-overline {
  font-family: var(--kvyk-font-mono);
  font-weight: var(--kvyk-weight-medium);
  font-size: 12px;
  line-height: 16px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-mono { font-family: var(--kvyk-font-mono); }
/* A paragraph in a body size is running text, so it takes the body leading.
   The same class on a span in the UI (an option's hint) keeps its line. */
p:is(.kvyk-body-lg, .kvyk-body-md, .kvyk-body-sm) { line-height: var(--kvyk-leading-body); }

/* Fluid down-scaling of the largest type on small screens */
@media (max-width: 600px) {
  .kvyk-display-lg { font-size: 36px; }
  .kvyk-headline-lg { font-size: 26px; }
}

/* ==========================================================================
   5. LAYOUT PRIMITIVES
   ========================================================================== */
.kvyk-container {
  width: 100%;
  max-width: var(--kvyk-max-width);
  margin-inline: auto;
  padding-inline: var(--kvyk-margin-mobile);
}
@media (min-width: 768px) {
  .kvyk-container { padding-inline: var(--kvyk-margin-desktop); }
}

/* Vertical rhythm: stack children with a gap (default 16px). */
.kvyk-stack {
  --_flow-gap: var(--kvyk-stack-gap, var(--kvyk-space-md));
  display: flex;
  flex-direction: column;
  gap: var(--_flow-gap);
}
.kvyk-stack--xs { --kvyk-stack-gap: var(--kvyk-space-xs); }
.kvyk-stack--sm { --kvyk-stack-gap: var(--kvyk-space-sm); }
.kvyk-stack--lg { --kvyk-stack-gap: var(--kvyk-space-lg); }
.kvyk-stack--xl { --kvyk-stack-gap: var(--kvyk-space-xl); }

/* Text after text, the same everywhere, whatever stack holds it: paragraphs
   (and a paragraph and a list) --kvyk-space-paragraph apart, a title and the
   line under it --kvyk-space-lead. Each container below states its own gap as
   --_flow-gap (block ones 0), and the margin makes up only what that gap
   lacks, so gap and margin never add up past the value. A wider gap wins. */
:where(.kvyk-card, .kvyk-card__header, .kvyk-card__body, .kvyk-alert > div) { --_flow-gap: 0px; }
:where(.kvyk-stack, .kvyk-section, .kvyk-section__header, .kvyk-section__body, .kvyk-field, .kvyk-page-header__text, .kvyk-card, .kvyk-card__header, .kvyk-card__body, .kvyk-alert > div)
  > :where(p:not([class]), p:is(.kvyk-body-lg, .kvyk-body-md, .kvyk-body-sm, .kvyk-help, .kvyk-alert__body, .kvyk-section__lead):not(.kvyk-mono), ul:not([class]), ol:not([class]))
  + :where(p:not([class]), p:is(.kvyk-body-lg, .kvyk-body-md, .kvyk-body-sm, .kvyk-help, .kvyk-alert__body, .kvyk-section__lead):not(.kvyk-mono), ul:not([class]), ol:not([class])) {
  margin-top: max(0px, calc(var(--kvyk-space-paragraph) - var(--_flow-gap)));
}
:where(.kvyk-stack, .kvyk-section, .kvyk-section__header, .kvyk-section__body, .kvyk-field, .kvyk-page-header__text, .kvyk-card, .kvyk-card__header, .kvyk-card__body, .kvyk-alert > div)
  > :where(h1, h2, h3, h4, h5, h6, .kvyk-display-lg, .kvyk-headline-lg, .kvyk-headline-md, .kvyk-title, .kvyk-section__title)
  + :where(p:not([class]), p:is(.kvyk-body-lg, .kvyk-body-md, .kvyk-body-sm, .kvyk-help, .kvyk-section__lead):not(.kvyk-mono)) {
  margin-top: max(0px, calc(var(--kvyk-space-lead) - var(--_flow-gap)));
}

/* Horizontal group that wraps; vertically centered. */
.kvyk-cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kvyk-cluster-gap, var(--kvyk-space-sm));
}
.kvyk-cluster--md { --kvyk-cluster-gap: var(--kvyk-space-md); }
.kvyk-cluster--xs { --kvyk-cluster-gap: var(--kvyk-space-xs); }
.kvyk-cluster--lg { --kvyk-cluster-gap: var(--kvyk-space-lg); }
.kvyk-cluster--between { justify-content: space-between; flex-wrap: nowrap; }

/* Responsive auto grid; collapses to 1 column on small screens. */
.kvyk-grid {
  display: grid;
  gap: var(--kvyk-grid-gap, var(--kvyk-gutter));
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
}
@media (min-width: 768px) {
  .kvyk-grid--2 { grid-template-columns: repeat(2, 1fr); }
  .kvyk-grid--3 { grid-template-columns: repeat(3, 1fr); }
  .kvyk-grid--4 { grid-template-columns: repeat(4, 1fr); }
}

.kvyk-divider { border: none; border-top: 1px solid var(--kvyk-outline-variant); }
/* A divider across the whole scrolling column, edge to edge: it reaches far
   out both sides and the column (.kvyk-main) clips it. Under a page's title. */
.kvyk-divider--full { margin-inline: -100vw; }
.kvyk-divider--v {
  border-top: none;
  border-left: 1px solid var(--kvyk-outline-variant);
  align-self: stretch;
  width: 0;
}

/* Signature dot-grid texture for hero / canvas backgrounds. */
.kvyk-dotgrid {
  background-image: radial-gradient(var(--kvyk-outline-variant) 1px, transparent 1px);
  background-size: 24px 24px;
}
.kvyk-dotgrid--subtle {
  background-image: radial-gradient(var(--kvyk-on-surface) 1px, transparent 1px);
  background-size: 24px 24px;
  opacity: 0.03;
}

/* Frosted panel (used for the AI console over a textured canvas). */
.kvyk-glass {
  background: rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(198, 198, 205, 0.6);
}

/* ---- Application shell --------------------------------------------------- */
/* A white sidebar beside a scrolling main column. The sidebar's brand band and
   the app bar share the header height and its bottom rule, so the two read as
   one white header across the top, as on the public site. */
.kvyk-app-shell {
  display: flex;
  height: 100vh;
  width: 100%;
  overflow: hidden;
}
.kvyk-sidebar {
  /* Nav items pad their text 12px in from the body's edge; the brand, labels and
     footer line their text up with it. */
  --_edge: var(--kvyk-space-md);
  --_text: calc(var(--kvyk-space-md) + 12px);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  width: var(--kvyk-sidebar-width);
  height: 100%;
  background: var(--kvyk-surface-container-lowest);
  border-right: 1px solid var(--kvyk-outline-variant);
  z-index: var(--kvyk-z-nav);
}
.kvyk-sidebar__brand {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  height: var(--kvyk-header-height);
  padding-inline: var(--_text);
  border-bottom: 1px solid var(--kvyk-outline-variant);
}
.kvyk-sidebar__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-lg);
  padding: var(--kvyk-space-lg) var(--_edge);
}
/* Lines content up with the nav items' text. */
.kvyk-sidebar__inset { padding-inline: 12px; }
.kvyk-sidebar__label {
  display: block;
  padding-inline: 12px;
  margin-bottom: var(--kvyk-space-sm);
}
.kvyk-sidebar__footer {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-sm);
  padding: var(--kvyk-space-md) var(--_text);
  border-top: 1px solid var(--kvyk-outline-variant);
}
/* The person's own links (their approvals, their notifications) sit in the
   footer above the account, their items on the body's edge like the nav's. */
.kvyk-sidebar__footer > .kvyk-nav {
  align-self: stretch;
  margin-inline: calc(var(--_edge) - var(--_text));
}
.kvyk-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  background: var(--kvyk-background);
}
/* On a desktop the sidebar narrows to its icons and back, from the button in
   its brand band; each item then keeps its name for screen readers and shows
   it on hover. The organisation menu and the account's name step aside. */
.kvyk-sidebar__collapse { margin-left: auto; }
@media (min-width: 768px) {
  .kvyk-sidebar.is-collapsed {
    --_edge: var(--kvyk-space-sm);
    width: var(--kvyk-sidebar-width-collapsed);
  }
  .kvyk-sidebar.is-collapsed .kvyk-sidebar__brand { justify-content: center; padding-inline: 0; }
  .kvyk-sidebar.is-collapsed .kvyk-sidebar__brand .kvyk-brand { display: none; }
  .kvyk-sidebar.is-collapsed .kvyk-sidebar__collapse { margin-left: 0; }
  .kvyk-sidebar.is-collapsed .kvyk-sidebar__orgs > .kvyk-combobox { display: none; }
  .kvyk-sidebar.is-collapsed .kvyk-nav-item { justify-content: center; padding-inline: 0; }
  .kvyk-sidebar.is-collapsed .kvyk-nav-item > .kvyk-icon--sm { display: none; }
  .kvyk-sidebar.is-collapsed .kvyk-nav-item:has(> .kvyk-count) { position: relative; }
  .kvyk-sidebar.is-collapsed .kvyk-nav-item > .kvyk-count {
    position: absolute;
    top: 0;
    right: 2px;
  }
  .kvyk-sidebar.is-collapsed .kvyk-nav--nested { padding-left: 0; }
  .kvyk-sidebar.is-collapsed .kvyk-nav-item__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
  .kvyk-sidebar.is-collapsed .kvyk-sidebar__footer { padding-inline: 0; align-items: center; }
  .kvyk-sidebar.is-collapsed .kvyk-sidebar__footer > .kvyk-nav { margin-inline: var(--_edge); }
  .kvyk-sidebar.is-collapsed .kvyk-sidebar__footer .kvyk-cluster { flex-direction: column; }
  .kvyk-sidebar.is-collapsed .kvyk-sidebar__footer .kvyk-cluster > a { display: none; }
}
/* Below 768px the sidebar is a drawer: hidden until the app bar's menu button
   opens it over the page, a scrim behind it and a close button in its brand band. */
.kvyk-appbar .kvyk-appbar__menu,
.kvyk-sidebar .kvyk-sidebar__close { display: none; }
@media (max-width: 767px) {
  .kvyk-sidebar { display: none; }
  .kvyk-sidebar .kvyk-sidebar__collapse { display: none; }
  .kvyk-sidebar.is-open {
    display: flex;
    position: fixed;
    inset: 0 auto 0 0;
    width: min(var(--kvyk-sidebar-width), 85vw);
    z-index: var(--kvyk-z-overlay);
    box-shadow: var(--kvyk-elevation-3);
  }
  .kvyk-sidebar-scrim {
    position: fixed;
    inset: 0;
    z-index: calc(var(--kvyk-z-overlay) - 1);
    background: var(--kvyk-scrim);
  }
  .kvyk-appbar .kvyk-appbar__menu { display: inline-flex; }
  .kvyk-sidebar .kvyk-sidebar__close { display: inline-flex; margin-left: auto; }
}

/* App top bar: sticks to the top of the scrolling main column, frosted over it. */
.kvyk-appbar {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--kvyk-space-md);
  height: var(--kvyk-header-height);
  flex-shrink: 0;
  padding-inline: var(--kvyk-margin-desktop);
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--kvyk-outline-variant);
  z-index: var(--kvyk-z-header);
}
@media (max-width: 767px) {
  .kvyk-appbar { padding-inline: var(--kvyk-margin-mobile); }
}
/* The bar's breadcrumbs fill it between the menu button and its controls;
   below 768px they drop to a band of their own under the bar. */
.kvyk-appbar__trail { flex: 1; min-width: 0; }
@media (max-width: 767px) {
  .kvyk-appbar:has(> .kvyk-appbar__trail) {
    display: grid;
    grid-template-columns: auto auto;
    grid-template-rows: var(--kvyk-header-height) auto;
    justify-content: space-between;
    row-gap: 0;
    height: auto;
  }
  .kvyk-appbar__trail {
    grid-row: 2;
    grid-column: 1 / -1;
    margin-inline: calc(-1 * var(--kvyk-margin-mobile));
    padding: var(--kvyk-space-sm) var(--kvyk-margin-mobile);
    border-top: 1px solid var(--kvyk-outline-variant);
  }
}

/* A page in the main column: the container's width, with room above and below. */
.kvyk-page {
  padding-block: var(--kvyk-space-xl) var(--kvyk-space-2xl);
}

/* The rhythm of a page: its header on the tinted canvas, then each of its
   sections a white, square, outlined surface, with space between them. A
   section inside a section is part of its surface, not one of its own. */
:root {
  --kvyk-surface-pad: var(--kvyk-space-xl);
  --kvyk-surface-gap: var(--kvyk-space-xl);
}
@media (max-width: 767px) {
  :root {
    --kvyk-surface-pad: calc(var(--kvyk-space-md) + var(--kvyk-space-xs));
    --kvyk-surface-gap: var(--kvyk-space-lg);
  }
}
.kvyk-page-body {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-surface-gap);
}
/* Sections side by side keep the same space between them as stacked ones. */
.kvyk-page-body > .kvyk-grid { --kvyk-grid-gap: var(--kvyk-surface-gap); }
.kvyk-page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--kvyk-space-md) var(--kvyk-space-lg);
}
.kvyk-page-header__text {
  --_flow-gap: var(--kvyk-space-sm);
  display: flex;
  flex-direction: column;
  gap: var(--_flow-gap);
  min-width: 0;
}
.kvyk-page-header > .kvyk-page-header__text { flex: 1 1 20rem; }
.kvyk-page-header__text > p { max-width: var(--kvyk-measure); color: var(--kvyk-on-surface-variant); }
/* A page header that stays under the app bar and Ask kvyk while its page scrolls, so an
   index keeps its first action in reach however long its list grows. */
.kvyk-page-header--sticky {
  position: sticky;
  top: calc(var(--kvyk-header-height) + var(--kvyk-askbar-height));
  z-index: calc(var(--kvyk-z-header) - 1);
  margin-block: calc(-1 * var(--kvyk-space-sm));
  padding-block: var(--kvyk-space-sm);
  background: var(--kvyk-background);
}
.kvyk-page-header__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kvyk-space-sm);
}
.kvyk-section {
  --_flow-gap: var(--kvyk-stack-gap, var(--kvyk-space-md));
  display: flex;
  flex-direction: column;
  gap: var(--_flow-gap);
  min-width: 0;
}
.kvyk-page-body .kvyk-section:not(.kvyk-section .kvyk-section) {
  padding: var(--kvyk-surface-pad);
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
}
/* A list in a section runs to the surface's edges, its row lines with it,
   and its first and last columns line up with the section's text, so the
   section reads as one block instead of a box in a box. One kept to the
   fields' width keeps its frame. */
.kvyk-page-body .kvyk-section:not(.kvyk-section .kvyk-section) :is(.kvyk-table-wrap, .kvyk-table-panel, .kvyk-list):not(.kvyk-table-panel > *, .kvyk-section__body *) {
  margin-inline: calc(-1 * var(--kvyk-surface-pad));
  border-inline: 0;
  border-radius: 0;
}
.kvyk-page-body .kvyk-section:not(.kvyk-section .kvyk-section) > :is(.kvyk-table-wrap, .kvyk-table-panel, .kvyk-list):first-child {
  margin-top: calc(-1 * var(--kvyk-surface-pad));
  border-top: 0;
}
.kvyk-page-body .kvyk-section:not(.kvyk-section .kvyk-section) > :is(.kvyk-table-wrap, .kvyk-table-panel, .kvyk-list):last-child {
  margin-bottom: calc(-1 * var(--kvyk-surface-pad));
  border-bottom: 0;
}
.kvyk-page-body .kvyk-section:not(.kvyk-section .kvyk-section) .kvyk-table:not(.kvyk-section__body *) :is(th, td):first-child { padding-left: var(--kvyk-surface-pad); }
.kvyk-page-body .kvyk-section:not(.kvyk-section .kvyk-section) .kvyk-table:not(.kvyk-section__body *) :is(th, td):last-child { padding-right: var(--kvyk-surface-pad); }
.kvyk-page-body .kvyk-section:not(.kvyk-section .kvyk-section) :is(.kvyk-table-footer, .kvyk-list-item):not(.kvyk-section__body *) { padding-inline: var(--kvyk-surface-pad); }
/* A field straight in a section keeps a readable width. */
.kvyk-section > .kvyk-field { max-width: var(--kvyk-measure); }
/* A section's title, with a line under it when it needs one. */
.kvyk-section__header {
  --_flow-gap: var(--kvyk-space-xs);
  display: flex;
  flex-direction: column;
  gap: var(--_flow-gap);
  min-width: 0;
}
/* A section's header with its actions on the right. */
.kvyk-section__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--kvyk-space-sm) var(--kvyk-space-md);
}
/* A section's fields: a readable width, not the page's. */
.kvyk-section__body {
  --_flow-gap: var(--kvyk-space-md);
  display: flex;
  flex-direction: column;
  gap: var(--_flow-gap);
  max-width: var(--kvyk-measure);
  min-width: 0;
}
/* A section's actions, after its fields: the main one first. */
.kvyk-section__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kvyk-space-sm);
}
.kvyk-section__title {
  margin: 0;
  font-family: var(--kvyk-font-sans);
  font-size: 16px;
  line-height: var(--kvyk-leading-heading);
  font-weight: var(--kvyk-weight-semibold);
  color: var(--kvyk-on-surface);
}
.kvyk-section__lead {
  max-width: var(--kvyk-measure);
  font-size: 14px;
  line-height: var(--kvyk-leading-body);
  color: var(--kvyk-on-surface-variant);
}
/* Short terms with what each means, the meanings lined up in one column;
   on a phone each meaning goes under its term. */
.kvyk-terms {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--kvyk-space-sm) var(--kvyk-space-lg);
  max-width: var(--kvyk-measure);
  margin: 0;
  font-size: 14px;
  line-height: 20px;
}
.kvyk-terms dt { font-weight: var(--kvyk-weight-semibold); color: var(--kvyk-on-surface); }
.kvyk-terms dd { margin: 0; color: var(--kvyk-on-surface-variant); }
@media (max-width: 479px) {
  .kvyk-terms { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  .kvyk-terms dd + dt { margin-top: var(--kvyk-space-sm); }
}

/* A row of controls over a list: its search on the left, what acts on the
   whole list on the right. */
.kvyk-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--kvyk-space-sm) var(--kvyk-space-md);
}

/* A quiet control over a page, on its right: who the page is seen as. */
.kvyk-view-as {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--kvyk-space-sm);
}
.kvyk-view-as__picker { flex: 0 1 18rem; min-width: 12rem; }
.kvyk-view-as .kvyk-combobox { min-width: 0; }
.kvyk-sidebar__orgs > .kvyk-combobox { min-width: 0; }
.kvyk-view-as .kvyk-input { height: var(--kvyk-control-height-sm); font-size: 14px; }

/* Labelled values, as many columns as fit: the label small and muted above. */
.kvyk-details {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(16rem, 100%), 1fr));
  gap: var(--kvyk-space-lg);
  margin: 0;
}
.kvyk-details > div { display: flex; flex-direction: column; gap: var(--kvyk-space-xs); min-width: 0; }
.kvyk-details dt {
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  line-height: 16px;
  font-weight: var(--kvyk-weight-medium);
  color: var(--kvyk-on-surface-variant);
}
.kvyk-details dd { margin: 0; overflow-wrap: anywhere; }

/* Nothing here yet: a calm block that says so and offers the way on. */
.kvyk-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--kvyk-space-md);
  padding: var(--kvyk-space-2xl) var(--kvyk-space-lg);
  text-align: center;
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
}
.kvyk-empty > p { max-width: 36rem; color: var(--kvyk-on-surface-variant); }

/* Convenience surface backgrounds */
.kvyk-surface-card { background: var(--kvyk-surface-container-lowest); }
.kvyk-surface-low { background: var(--kvyk-surface-container-low); }
.kvyk-surface-1 { background: var(--kvyk-surface-container); }
.kvyk-surface-2 { background: var(--kvyk-surface-container-high); }
.kvyk-surface-3 { background: var(--kvyk-surface-container-highest); }

/* ==========================================================================
   6. COMPONENTS
   ========================================================================== */

/* ---- Icon ---------------------------------------------------------------- */
/* Inline SVG line icons: 24px grid, 2px stroke, currentColor.
   Use <svg class="kvyk-icon"><use href="#i-search"/></svg>. */
.kvyk-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.kvyk-icon--sm { width: 16px; height: 16px; }
.kvyk-icon--lg { width: 24px; height: 24px; }
.kvyk-icon--xl { width: 32px; height: 32px; }
.kvyk-icon--solid { fill: currentColor; stroke: none; }

/* Square tile that frames an icon (feature cards, etc.) */
.kvyk-icon-tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: var(--kvyk-radius-md);
  background: var(--kvyk-surface-container);
  color: var(--kvyk-secondary);
  flex-shrink: 0;
}
.kvyk-icon-tile--sm { width: 40px; height: 40px; }
.kvyk-icon-tile--round { border-radius: var(--kvyk-radius-circle); }
.kvyk-icon-tile--accent { background: var(--kvyk-secondary-container); color: var(--kvyk-on-secondary-container); }
.kvyk-icon-tile--success { background: var(--kvyk-tertiary-fixed-dim); color: var(--kvyk-on-tertiary-fixed-variant); }
.kvyk-icon-tile--danger { background: var(--kvyk-error-container); color: var(--kvyk-on-error-container); }

/* ---- Button -------------------------------------------------------------- */
.kvyk-btn {
  /* themeable locals — variants only re-map these */
  --_bg: var(--kvyk-surface-container);
  --_fg: var(--kvyk-on-surface);
  --_bd: transparent;
  --_bg-hover: var(--kvyk-surface-container-high);
  --_shadow: none;
  --_shadow-hover: none;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--kvyk-space-sm);
  height: 40px;
  padding-inline: var(--kvyk-space-md);
  font-family: var(--kvyk-font-mono);
  font-size: 14px;
  line-height: 20px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.02em;
  color: var(--_fg);
  background: var(--_bg);
  border: 1px solid var(--_bd);
  border-radius: var(--kvyk-radius-sm);
  box-shadow: var(--_shadow);
  white-space: nowrap;
  user-select: none;
  text-decoration: none;
  transition: background-color var(--kvyk-duration) var(--kvyk-ease),
              color var(--kvyk-duration) var(--kvyk-ease),
              border-color var(--kvyk-duration) var(--kvyk-ease),
              box-shadow var(--kvyk-duration) var(--kvyk-ease),
              transform var(--kvyk-duration-fast) var(--kvyk-ease);
}
.kvyk-btn:hover { background: var(--_bg-hover); box-shadow: var(--_shadow-hover); text-decoration: none; }
.kvyk-btn:active { transform: translateY(1px); }
.kvyk-btn:disabled,
.kvyk-btn[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }
.kvyk-btn .kvyk-icon { width: 18px; height: 18px; }

.kvyk-btn--primary {
  --_bg: var(--kvyk-primary);
  --_fg: var(--kvyk-on-primary);
  --_bg-hover: var(--kvyk-inverse-surface);
}
.kvyk-btn--accent {
  --_bg: var(--kvyk-secondary);
  --_fg: var(--kvyk-on-secondary);
  --_bg-hover: var(--kvyk-secondary-hover);
}
.kvyk-btn--tonal {
  --_bg: var(--kvyk-secondary-fixed);
  --_fg: var(--kvyk-on-secondary-fixed);
  --_bg-hover: var(--kvyk-secondary-fixed-dim);
}
.kvyk-btn--outline {
  --_bg: transparent;
  --_fg: var(--kvyk-on-surface);
  --_bd: var(--kvyk-outline);
  --_bg-hover: var(--kvyk-surface-container-low);
}
.kvyk-btn--ghost {
  --_bg: transparent;
  --_fg: var(--kvyk-on-surface-variant);
  --_bg-hover: var(--kvyk-surface-container-low);
}
.kvyk-btn--danger {
  --_bg: var(--kvyk-error);
  --_fg: var(--kvyk-on-error);
  --_bg-hover: var(--kvyk-on-error-container);
}
/* A filled button that cannot be used yet goes neutral, rather than a faded
   colour that still reads as the main action. Its hover colour goes neutral
   too: a button disabled under the pointer or a tap (a send button while its
   message goes out) keeps :hover until the pointer moves, which would put the
   neutral text on the accent colour. */
.kvyk-btn--primary:disabled,
.kvyk-btn--accent:disabled,
.kvyk-btn--danger:disabled,
.kvyk-btn--tonal:disabled {
  --_bg: var(--kvyk-surface-container);
  --_bg-hover: var(--kvyk-surface-container);
  --_fg: var(--kvyk-on-surface-variant);
  opacity: 1;
}
/* Raised: the hero CTA with a colored glow that lifts on hover. */
.kvyk-btn--raised {
  --_shadow: var(--kvyk-elevation-accent);
  --_shadow-hover: var(--kvyk-elevation-accent-hover);
}

.kvyk-btn--sm { height: 32px; padding-inline: var(--kvyk-space-sm); font-size: 12px; }
.kvyk-btn--lg { height: 48px; padding-inline: var(--kvyk-space-lg); }
/* A full-width button wraps a label longer than the line, such as an app's
   name on a phone, instead of running out of the button. */
.kvyk-btn--block {
  width: 100%;
  height: auto;
  min-height: var(--kvyk-control-height);
  padding-block: var(--kvyk-space-sm);
  white-space: normal;
  text-align: center;
}
.kvyk-btn--block.kvyk-btn--lg { min-height: 48px; }
/* A big tap target in a grid of them, such as a name on a shared device's
   screen: as tall as two lines, its label and a note under it centred. */
.kvyk-btn--tile {
  flex-direction: column;
  gap: var(--kvyk-space-2xs);
  width: 100%;
  height: auto;
  min-height: 64px;
  padding: var(--kvyk-space-sm) var(--kvyk-space-md);
  white-space: normal;
  text-align: center;
}
/* Shown where a button would be, but nothing to press now: dashed and quiet. */
.kvyk-btn--unavailable {
  --_bg: transparent;
  --_fg: var(--kvyk-on-surface-variant);
  --_bd: var(--kvyk-outline);
  --_bg-hover: transparent;
  border-style: dashed;
  cursor: default;
}
.kvyk-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(9rem, 100%), 1fr));
  gap: var(--kvyk-space-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}
.kvyk-tiles > li { display: flex; }
/* A tile to pick, among others (a file of the library): a flush card that is a
   button, a preview over its caption, outlined in the accent with a check in
   its corner once picked (aria-pressed). */
.kvyk-pick-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  overflow: hidden;
  padding: 0;
  font: inherit;
  text-align: start;
  color: inherit;
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  cursor: pointer;
  transition: box-shadow var(--kvyk-duration) var(--kvyk-ease), border-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-pick-tile:hover { box-shadow: var(--kvyk-elevation-2); }
.kvyk-pick-tile:focus-visible { outline: none; box-shadow: var(--kvyk-ring); }
.kvyk-pick-tile[aria-pressed="true"] { border-color: var(--kvyk-secondary); box-shadow: 0 0 0 1px var(--kvyk-secondary); }
.kvyk-pick-tile__preview {
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  color: var(--kvyk-on-surface-variant);
  background: var(--kvyk-surface-container-low);
}
.kvyk-pick-tile__preview > img { display: block; width: 100%; height: 100%; object-fit: cover; }
.kvyk-pick-tile__caption {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  padding: var(--kvyk-space-xs) var(--kvyk-space-sm) var(--kvyk-space-sm);
}
.kvyk-pick-tile__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kvyk-pick-tile__meta {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-xs);
  min-width: 0;
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-regular);
  font-size: 11px;
  line-height: 16px;
  color: var(--kvyk-outline);
  white-space: nowrap;
}
.kvyk-pick-tile__meta > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kvyk-pick-tile__stage { position: absolute; top: var(--kvyk-space-xs); left: var(--kvyk-space-xs); }
.kvyk-pick-tile__stage.kvyk-badge { --_bg: var(--kvyk-surface-container-lowest); }
.kvyk-pick-tile__check {
  position: absolute;
  top: var(--kvyk-space-xs);
  right: var(--kvyk-space-xs);
  display: none;
  place-items: center;
  width: 24px;
  height: 24px;
  color: var(--kvyk-on-secondary);
  background: var(--kvyk-secondary);
  border-radius: var(--kvyk-radius-pill);
}
.kvyk-pick-tile[aria-pressed="true"] .kvyk-pick-tile__check { display: grid; }
.kvyk-pick-tile__check .kvyk-icon { width: 16px; height: 16px; }

/* Icon-only button (square or circular) */
.kvyk-btn--icon {
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: var(--kvyk-radius-circle);
}
.kvyk-btn--icon.kvyk-btn--sm { width: 32px; height: 32px; }
.kvyk-btn--icon .kvyk-icon { width: 20px; height: 20px; }

/* ---- Badge / Chip / Tag -------------------------------------------------- */
.kvyk-badge {
  --_bg: var(--kvyk-surface-container-low);
  --_fg: var(--kvyk-on-surface-variant);
  display: inline-flex;
  align-items: center;
  gap: var(--kvyk-space-xs);
  padding: 2px 8px;
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  line-height: 16px;
  font-weight: var(--kvyk-weight-medium);
  color: var(--_fg);
  background: var(--_bg);
  border-radius: var(--kvyk-radius-pill);
  white-space: nowrap;
}
.kvyk-badge--accent { --_bg: var(--kvyk-secondary-fixed); --_fg: var(--kvyk-on-secondary-fixed); }
/* A badge that can be taken away, as an active filter is: its remove button. */
.kvyk-badge__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  margin-right: -4px;
  padding: 0;
  color: inherit;
  background: transparent;
  border: none;
  border-radius: var(--kvyk-radius-pill);
  cursor: pointer;
}
.kvyk-badge__remove:hover { background: var(--kvyk-surface-container-high); color: var(--kvyk-on-surface); }
.kvyk-badge__remove .kvyk-icon { width: 12px; height: 12px; }
/* Status badges carry their colour in a hairline and the text, never a
   bright fill, so a column of them stays calm. */
.kvyk-badge--success {
  --_bg: transparent;
  --_fg: var(--kvyk-on-tertiary-fixed-variant);
  box-shadow: inset 0 0 0 1px var(--kvyk-tertiary-fixed-dim);
}
.kvyk-badge--danger {
  --_bg: transparent;
  --_fg: var(--kvyk-on-error-container);
  box-shadow: inset 0 0 0 1px var(--kvyk-error);
}
.kvyk-badge--outline {
  --_bg: transparent;
  box-shadow: inset 0 0 0 1px var(--kvyk-outline-variant);
}
.kvyk-badge--square { border-radius: var(--kvyk-radius-xs); }
.kvyk-badge .kvyk-icon { width: 14px; height: 14px; }

/* Leading status dot */
.kvyk-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--kvyk-radius-circle);
  background: var(--kvyk-outline);
  flex-shrink: 0;
}
.kvyk-dot--accent { background: var(--kvyk-secondary); }
.kvyk-dot--success { background: var(--kvyk-tertiary-fixed-dim); }
.kvyk-dot--danger { background: var(--kvyk-error); }
.kvyk-dot--pulse { animation: kvyk-pulse 2s var(--kvyk-ease) infinite; }

/* Which stage's data a page shows: a status beside a page's buttons, as tall
   as they are, so it lines up with them, yet no frame, fill or hover, so it is
   never taken for one. Live is real data and wears the success green; Preview
   a hollow dot. */
.kvyk-stage {
  --_dot: var(--kvyk-outline);
  --_fg: var(--kvyk-on-surface-variant);
  display: inline-flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  height: var(--kvyk-control-height);
  padding-inline: var(--kvyk-space-xs);
  font-family: var(--kvyk-font-mono);
  font-size: 13px;
  line-height: 20px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.02em;
  color: var(--_fg);
  white-space: nowrap;
  cursor: default;
}
.kvyk-stage::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: var(--kvyk-radius-circle);
  box-shadow: inset 0 0 0 2px var(--_dot);
  flex-shrink: 0;
}
.kvyk-stage--live {
  --_dot: var(--kvyk-on-tertiary-container);
  --_fg: var(--kvyk-on-tertiary-fixed-variant);
}
.kvyk-stage--live::before { background: var(--_dot); }

/* A count of things waiting, such as conversations with an answer not yet
   read: a small filled pill in the accent, at the end of a nav item or on an
   icon button's corner. It is only seen; the control's name says the count. */
.kvyk-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  font-family: var(--kvyk-font-mono);
  font-size: 11px;
  line-height: 1;
  font-weight: var(--kvyk-weight-semibold);
  letter-spacing: 0;
  color: var(--kvyk-on-secondary);
  background: var(--kvyk-secondary);
  border-radius: var(--kvyk-radius-pill);
  flex-shrink: 0;
}
.kvyk-nav-item > .kvyk-count { margin-left: auto; }
.kvyk-btn--icon:has(> .kvyk-count) { position: relative; }
.kvyk-btn--icon > .kvyk-count {
  position: absolute;
  top: 2px;
  right: 0;
}

@keyframes kvyk-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

/* Something is being worked on, such as a file being checked: a small ring
   that turns, sized for a badge or a chip. It says nothing itself, so give it
   role="img" and an aria-label naming what is happening. Without motion it
   stands still as a dotted ring. */
.kvyk-spinner {
  --_size: 14px;
  display: inline-block;
  width: var(--_size);
  height: var(--_size);
  flex-shrink: 0;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--kvyk-radius-circle);
  animation: kvyk-spin 0.8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .kvyk-spinner {
    animation: none !important;
    border-style: dotted;
    border-top-color: currentColor;
  }
}

@keyframes kvyk-spin {
  to { transform: rotate(360deg); }
}

/* ---- Card ---------------------------------------------------------------- */
.kvyk-card {
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  padding: var(--kvyk-space-lg);
}
.kvyk-card--flush { padding: 0; }
/* A table or list straight in a flush card runs to its edges: the card's
   border and its header's rule frame it, not a second border of its own. */
.kvyk-card--flush > :is(.kvyk-table-wrap, .kvyk-table-panel, .kvyk-list) {
  border: 0;
  border-radius: 0;
}
.kvyk-card--flush > :is(.kvyk-table-wrap, .kvyk-table-panel, .kvyk-list):last-child {
  border-radius: 0 0 calc(var(--kvyk-radius-card) - 1px) calc(var(--kvyk-radius-card) - 1px);
}
.kvyk-card--lg { padding: var(--kvyk-space-xl); }
.kvyk-card--raised { box-shadow: var(--kvyk-elevation-2); }
.kvyk-card--floating { border-color: transparent; box-shadow: var(--kvyk-elevation-3); }
.kvyk-card--interactive {
  cursor: pointer;
  transition: box-shadow var(--kvyk-duration) var(--kvyk-ease),
              transform var(--kvyk-duration) var(--kvyk-ease),
              border-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-card--interactive:hover {
  box-shadow: var(--kvyk-elevation-2);
  transform: translateY(-2px);
}

/* ---- Entry page ----------------------------------------------------------- */
/* A page on its own, before an app opens (its sign-in, what went wrong, a
   shared device's screen): the dashboard's sign-in card, a raised flush card
   with its header and body, in a column at the top of the background, with
   the organisation's logo above its title.
   <main class="kvyk-entry"><div class="kvyk-card kvyk-card--flush kvyk-card--raised kvyk-entry__card">… */
.kvyk-entry {
  display: grid;
  justify-items: center;
  align-content: start;
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--kvyk-space-3xl) var(--kvyk-margin-mobile);
}
.kvyk-entry__card { width: min(28rem, 100%); }
.kvyk-entry--wide .kvyk-entry__card { width: min(var(--kvyk-measure), 100%); }
/* A link in running text is underlined, not told apart by colour alone (WCAG 1.4.1). */
.kvyk-entry a:not(.kvyk-btn, .kvyk-navlink) { text-decoration: underline; text-underline-offset: 2px; }
.kvyk-entry__logo {
  display: block;
  width: auto;
  height: auto;
  max-width: 12rem;
  max-height: 48px;
  margin-bottom: var(--kvyk-space-sm);
  object-fit: contain;
}
@media (max-width: 480px) {
  .kvyk-entry { padding-block: var(--kvyk-space-md); }
}

/* Card subsections (header / body / footer), split by a single rule on the
   card's own white. A banded card tints its header and footer, for a page of
   cards side by side (an organisation's home). */
.kvyk-card__header {
  padding: var(--kvyk-space-md) var(--kvyk-space-lg);
  border-bottom: 1px solid var(--kvyk-outline-variant);
}
.kvyk-card__body { padding: var(--kvyk-space-lg); }
.kvyk-card--banded > .kvyk-card__header,
.kvyk-card--banded > .kvyk-card__footer { background: var(--kvyk-surface-container-low); }
.kvyk-card__footer {
  padding: var(--kvyk-space-md) var(--kvyk-space-lg);
  border-top: 1px solid var(--kvyk-outline-variant);
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: var(--kvyk-space-sm);
}

/* ---- Stat card ----------------------------------------------------------- */
.kvyk-stat__label {
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.02em;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-stat__value {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-semibold);
  font-size: 32px;
  line-height: 40px;
  letter-spacing: -0.01em;
  color: var(--kvyk-on-surface);
}
.kvyk-stat__delta {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 1px 6px;
  border-radius: var(--kvyk-radius-xs);
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  font-weight: var(--kvyk-weight-medium);
  background: var(--kvyk-surface-container-high);
  color: var(--kvyk-on-surface-variant);
}
.kvyk-stat__delta--up { background: rgba(78, 222, 163, 0.2); color: var(--kvyk-on-tertiary-container); }
.kvyk-stat__delta--down { background: var(--kvyk-error-container); color: var(--kvyk-on-error-container); }
.kvyk-stat__delta .kvyk-icon { width: 14px; height: 14px; }

/* Tiny inline bar chart (decorative sparkline). */
.kvyk-sparkbars {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 48px;
}
.kvyk-sparkbars > span {
  flex: 1;
  background: var(--kvyk-secondary-fixed);
  border-radius: var(--kvyk-radius-xs) var(--kvyk-radius-xs) 0 0;
}
.kvyk-sparkbars > span:last-child { background: var(--kvyk-secondary); }

/* ---- Chart ----------------------------------------------------------------
   A chart drawn as inline SVG: thin marks from a shared baseline, a recessive
   axis, values in text colours and never in a series' colour. Series take
   the categorical colours in order (--kvyk-chart-1 first, the accent), never
   cycled: a seventh group folds into "Other". Three of them sit below 3:1 on
   white, so a chart always carries a legend and the numbers on hover, focus
   and in a table. */
.kvyk-chart {
  --kvyk-chart-1: var(--kvyk-secondary);
  --kvyk-chart-2: #eb6834;
  --kvyk-chart-3: #1baf7a;
  --kvyk-chart-4: #eda100;
  --kvyk-chart-5: #e87ba4;
  --kvyk-chart-6: #6250d6;
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-xs);
  margin: 0;
  min-height: 0;
  height: 100%;
}
.kvyk-chart__plot {
  position: relative;
  flex: 1;
  min-height: 96px;
}
.kvyk-chart__plot > svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.kvyk-chart__axis {
  stroke: var(--kvyk-outline-variant);
  stroke-width: 1;
}
.kvyk-chart__grid {
  stroke: var(--kvyk-outline-variant);
  stroke-width: 1;
  stroke-dasharray: 2 4;
}
.kvyk-chart__mark { transition: opacity var(--kvyk-duration-fast) var(--kvyk-ease); }
.kvyk-chart__hit { fill: transparent; }
.kvyk-chart__hit:focus { outline: none; }
.kvyk-chart__hit:focus-visible { fill: var(--kvyk-ring-color); }
.kvyk-chart.is-pointing .kvyk-chart__mark:not(.is-pointed) { opacity: 0.45; }
.kvyk-chart__line {
  fill: none;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.kvyk-chart__ticks {
  display: flex;
  justify-content: space-between;
  gap: var(--kvyk-space-sm);
  font-family: var(--kvyk-font-mono);
  font-size: 11px;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-chart__readout {
  font-size: 13px;
  color: var(--kvyk-on-surface-variant);
  min-height: 1.5em;
}
.kvyk-chart__readout strong { color: var(--kvyk-on-surface); font-weight: var(--kvyk-weight-semibold); }
.kvyk-chart__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--kvyk-space-xs) var(--kvyk-space-sm-md);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 12px;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-chart__legend li { display: inline-flex; align-items: center; gap: var(--kvyk-space-xs); }
.kvyk-chart__swatch {
  width: 10px;
  height: 10px;
  border-radius: var(--kvyk-radius-xs);
  flex: none;
}
/* Horizontal bars: a row per group, its name, its bar and its value. */
.kvyk-chart__rows {
  display: grid;
  grid-template-columns: minmax(4rem, max-content) 1fr max-content;
  align-items: center;
  gap: var(--kvyk-space-xs) var(--kvyk-space-sm);
  font-size: 13px;
  overflow-y: auto;
}
.kvyk-chart__rows > .kvyk-chart__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 12rem;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-chart__track { display: flex; gap: 2px; height: 14px; }
.kvyk-chart__track > span { border-radius: 0 var(--kvyk-radius-sm) var(--kvyk-radius-sm) 0; min-width: 0; }
.kvyk-chart__value {
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  color: var(--kvyk-on-surface);
  text-align: end;
}
/* One number, the headline, with how it moved against the period before.
   Centred only while it fits: a short card scrolls it instead of cutting
   off its top. */
.kvyk-chart--metric { justify-content: safe center; gap: 0; }

/* ---- Board ----------------------------------------------------------------
   Cards on a grid of twelve columns and rows of a fixed height, the same gap
   both ways. Each card sets its place in custom properties (--x and --y from
   0, --w and --h in cells), so below 768px the cards simply stack. Editing,
   a card moves by its header and grows by its corner; a dashed frame shows
   where it lands. */
.kvyk-board {
  --kvyk-board-row: 72px;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-rows: var(--kvyk-board-row);
  gap: var(--kvyk-space-md);
  position: relative;
}
.kvyk-board__card,
.kvyk-board__ghost {
  grid-column: calc(var(--x) + 1) / span var(--w);
  grid-row: calc(var(--y) + 1) / span var(--h);
  min-width: 0;
  min-height: 0;
}
.kvyk-board__card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
}
.kvyk-board__card:focus { outline: none; }
.kvyk-board__card:focus-visible { box-shadow: var(--kvyk-ring); border-color: var(--kvyk-secondary); }
.kvyk-board__head {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-xs);
  padding: var(--kvyk-space-sm) var(--kvyk-space-sm) var(--kvyk-space-sm) var(--kvyk-space-md);
  min-height: 44px;
}
.kvyk-board__title {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 14px;
  font-weight: var(--kvyk-weight-semibold);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kvyk-board__body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 0 var(--kvyk-space-md) var(--kvyk-space-sm);
}
.kvyk-board__foot {
  padding: 0 var(--kvyk-space-md) var(--kvyk-space-sm);
  font-size: 12px;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-board--editing .kvyk-board__head { cursor: grab; touch-action: none; }
.kvyk-board--editing .kvyk-board__card { border-style: dashed; }
.kvyk-board__card.is-moving {
  z-index: var(--kvyk-z-base);
  box-shadow: var(--kvyk-elevation-3);
  border-color: var(--kvyk-secondary);
  border-style: solid;
  opacity: 0.92;
  cursor: grabbing;
}
.kvyk-board__card.is-changed {
  border-color: var(--kvyk-secondary);
  box-shadow: 0 0 0 2px var(--kvyk-ring-color);
}
.kvyk-board__ghost {
  border: 2px dashed var(--kvyk-secondary);
  background: color-mix(in srgb, var(--kvyk-secondary-fixed) 40%, transparent);
  pointer-events: none;
}
.kvyk-board__resize {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  background:
    linear-gradient(135deg, transparent 50%, var(--kvyk-outline) 50%, var(--kvyk-outline) 60%, transparent 60%, transparent 70%, var(--kvyk-outline) 70%, var(--kvyk-outline) 80%, transparent 80%);
  cursor: nwse-resize;
  touch-action: none;
}
.kvyk-board__notice {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--kvyk-space-sm);
  height: 100%;
  font-size: 13px;
  color: var(--kvyk-on-surface-variant);
}
/* The card being edited, beside the board: a sheet from the right edge. */
.kvyk-board__editor {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: var(--kvyk-z-overlay);
  display: flex;
  flex-direction: column;
  width: min(560px, 100vw);
  background: var(--kvyk-surface-container-lowest);
  border-left: 1px solid var(--kvyk-outline-variant);
  box-shadow: var(--kvyk-elevation-3);
}
.kvyk-board__editor > header,
.kvyk-board__editor > footer {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  padding: var(--kvyk-space-md) var(--kvyk-space-lg);
  border-bottom: 1px solid var(--kvyk-outline-variant);
}
.kvyk-board__editor > footer {
  justify-content: flex-end;
  border-top: 1px solid var(--kvyk-outline-variant);
  border-bottom: 0;
}
.kvyk-board__editor > div {
  flex: 1;
  overflow-y: auto;
  padding: var(--kvyk-space-lg);
}
.kvyk-board__preview {
  display: flex;
  flex-direction: column;
  height: 240px;
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  padding: var(--kvyk-space-sm) var(--kvyk-space-md);
}
@media (max-width: 767px) {
  .kvyk-board { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; }
  .kvyk-board__card { grid-column: 1; grid-row: auto; height: calc(var(--h) * 56px); min-height: 160px; }
  .kvyk-board__ghost,
  .kvyk-board__resize { display: none; }
}

/* ---- Flow -----------------------------------------------------------------
   An automation as a flowchart, read top to bottom: a list of boxes joined by
   a line, each box saying its step in a sentence. A step that branches (a
   condition, a switch, parallel branches) lays its branches side by side
   under it, each a flow of its own with a label on top: its line forks into
   them and they join again below, before the next step. A loop frames its
   steps; a step's own failure branch hangs off its line to the side, on a red
   line under a red label (.kvyk-flow__fails). Wide branches
   scroll sideways in the flow's own frame, and below 768px they stack along
   a line on their left. Only tokens set its colours, so a theme that
   redefines them themes the flow. */
.kvyk-flow {
  --_line: var(--kvyk-outline-variant);
  --_gap: var(--kvyk-space-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}
.kvyk-flow--frame {
  align-items: stretch;
  overflow-x: auto;
  padding: var(--kvyk-space-lg);
  background: var(--kvyk-surface-container-low);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
}
.kvyk-flow--frame > .kvyk-flow__step { align-items: center; }
.kvyk-flow__step {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  min-width: 0;
}
.kvyk-flow__step + .kvyk-flow__step::before,
.kvyk-flow__branch > :is(.kvyk-flow, .kvyk-flow__empty)::before,
.kvyk-flow__fails-path > .kvyk-flow__label + .kvyk-flow::before {
  content: "";
  display: block;
  flex-shrink: 0;
  width: 2px;
  height: var(--_gap);
  background: var(--_line);
}
.kvyk-flow__box {
  --_accent: var(--kvyk-outline-variant);
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-xs);
  width: min(100%, 26rem);
  padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-left: 3px solid var(--_accent);
  border-radius: var(--kvyk-radius-md);
  color: var(--kvyk-on-surface);
  font: inherit;
  text-align: left;
}
button.kvyk-flow__box { cursor: pointer; }
button.kvyk-flow__box:hover { background: var(--kvyk-surface-hover); }
.kvyk-flow__box:focus { outline: none; }
.kvyk-flow__box:focus-visible { box-shadow: var(--kvyk-ring); border-color: var(--kvyk-secondary); }
.kvyk-flow__box--trigger { --_accent: var(--kvyk-secondary); background: var(--kvyk-surface-container-lowest); }
.kvyk-flow__box--logic { --_accent: var(--kvyk-on-surface-variant); }
.kvyk-flow__box--effect { --_accent: var(--kvyk-secondary-container); }
.kvyk-flow__box--code { --_accent: var(--kvyk-on-primary-fixed-variant); }
.kvyk-flow__box.is-selected { border-color: var(--kvyk-secondary); box-shadow: var(--kvyk-ring); }
.kvyk-flow__box.is-done { --_accent: var(--kvyk-on-tertiary-container); }
.kvyk-flow__box.is-running,
.kvyk-flow__box.is-waiting { --_accent: var(--kvyk-secondary); }
.kvyk-flow__box.is-waiting { border-style: dashed; border-left-style: solid; }
.kvyk-flow__box.is-failed,
.kvyk-flow__box.is-problem { --_accent: var(--kvyk-error); border-color: var(--kvyk-error); }
.kvyk-flow__box.is-skipped { opacity: 0.6; border-style: dashed; border-left-style: solid; }
.kvyk-flow__kind {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-xs);
  font-size: 11px;
  font-weight: var(--kvyk-weight-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-flow__kind .kvyk-icon { width: 14px; height: 14px; }
.kvyk-flow__sentence {
  margin: 0;
  font-size: 14px;
  line-height: var(--kvyk-leading-heading);
  overflow-wrap: anywhere;
}
.kvyk-flow__meta,
.kvyk-flow__caps {
  margin: 0;
  font-size: 12px;
  line-height: var(--kvyk-leading-heading);
  color: var(--kvyk-on-surface-variant);
  overflow-wrap: anywhere;
}
.kvyk-flow__caps { font-family: var(--kvyk-font-mono); }
.kvyk-flow__problem {
  margin: 0;
  font-size: 12px;
  color: var(--kvyk-error);
}
/* A step that fills a template shows a small drawing of its layout in the
   box's top corner: a page upright or on its side, or a mail with its band. */
.kvyk-flow__box:has(> .kvyk-flow__thumb) {
  min-height: calc(4.2rem + 2 * var(--kvyk-space-sm-md));
  padding-right: calc(3rem + 2 * var(--kvyk-space-md));
}
.kvyk-flow__thumb {
  position: absolute;
  top: var(--kvyk-space-sm-md);
  right: var(--kvyk-space-md);
  width: 3rem;
  height: auto;
}
.kvyk-flow__thumb-page { fill: var(--kvyk-surface-container-lowest); stroke: var(--kvyk-outline-variant); stroke-width: 0.75; }
.kvyk-flow__thumb-ink { fill: var(--kvyk-on-surface-variant); }
.kvyk-flow__thumb-soft { fill: var(--kvyk-outline-variant); }
.kvyk-flow__thumb-accent { fill: var(--kvyk-secondary); }
/* The step's line comes down to a bar that forks into the branches, and a
   second bar below gathers them again; each bar runs between the middles of
   the outer branches, so it never sticks out past them. */
.kvyk-flow__branches {
  --_fork: var(--kvyk-space-lg);
  --_stroke: linear-gradient(var(--_line), var(--_line));
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: var(--_fork);
  width: 100%;
  padding-block: var(--_gap);
  background:
    var(--_stroke) center top / 2px var(--_gap) no-repeat,
    var(--_stroke) center bottom / 2px var(--_gap) no-repeat;
}
/* Branches that end a flow only join; no line leads on. In a branch, that
   branch's own line takes over from where they join. */
.kvyk-flow__step:last-child > .kvyk-flow__branches:last-child {
  padding-bottom: 0;
  background-size: 2px var(--_gap), 0 0;
}
.kvyk-flow__branch {
  position: relative;
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  align-items: center;
  min-width: 14rem;
  padding-top: var(--_gap);
  background: var(--_stroke) center top / 2px var(--_gap) no-repeat;
}
.kvyk-flow__branch::before,
.kvyk-flow__branch::after {
  content: "";
  position: absolute;
  left: calc(var(--_fork) / -2);
  right: calc(var(--_fork) / -2);
  height: 2px;
  background: var(--_line);
}
.kvyk-flow__branch::before { top: 0; }
.kvyk-flow__branch::after { bottom: 0; }
.kvyk-flow__branch:first-child::before,
.kvyk-flow__branch:first-child::after { left: calc(50% - 1px); }
.kvyk-flow__branch:last-child::before,
.kvyk-flow__branch:last-child::after { right: calc(50% - 1px); }
/* A branch's line runs on from its last step down to the bar that joins
   them, however much shorter it is than the others. */
.kvyk-flow__branch > :is(.kvyk-flow, .kvyk-flow__empty) {
  display: flex;
  flex: 1 0 auto;
  flex-direction: column;
  align-items: center;
}
.kvyk-flow__branch > :is(.kvyk-flow, .kvyk-flow__empty)::after {
  content: "";
  flex: 1 0 var(--_gap);
  width: 2px;
  background: var(--_line);
}
.kvyk-flow__label {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  padding: var(--kvyk-space-2xs) var(--kvyk-space-sm);
  background: var(--kvyk-surface-container-high);
  border-radius: var(--kvyk-radius-pill);
  font-size: 12px;
  font-weight: var(--kvyk-weight-medium);
  color: var(--kvyk-on-surface);
  overflow-wrap: anywhere;
}
.kvyk-flow__empty {
  width: 100%;
  margin: 0;
  text-align: center;
  font-size: 12px;
  color: var(--kvyk-on-surface-variant);
}
/* Where a step can be added while the flow is edited: a small round plus on
   the line between two steps. */
.kvyk-flow__add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  padding: 0;
  background: var(--kvyk-surface-container-lowest);
  border: 1px dashed var(--kvyk-outline);
  border-radius: var(--kvyk-radius-pill);
  color: var(--kvyk-on-surface-variant);
  cursor: pointer;
}
.kvyk-flow__add:hover { background: var(--kvyk-surface-hover); color: var(--kvyk-on-surface); border-style: solid; }
.kvyk-flow__add:focus { outline: none; }
.kvyk-flow__add:focus-visible { box-shadow: var(--kvyk-ring); border-color: var(--kvyk-secondary); }
/* The automation editor's side panel: a setting that can be removed sits
   beside its remove button, and what is picked shows as a row of badges. */
.kvyk-automation-editor__row {
  display: flex;
  align-items: flex-start;
  gap: var(--kvyk-space-sm);
  padding: var(--kvyk-space-sm);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-md);
}
.kvyk-automation-editor__row > .kvyk-stack { flex: 1 1 auto; min-width: 0; }
.kvyk-automation-editor__chosen { margin: 0; padding: 0; list-style: none; }
/* The step picker: the kinds of step under their groups, each a row to press
   with its icon, its name and what it does in a line. */
.kvyk-step-picker .kvyk-list-item { padding: 0; }
.kvyk-step-picker__kind {
  display: flex;
  align-items: flex-start;
  gap: var(--kvyk-space-sm-md);
  width: 100%;
  padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.kvyk-step-picker__kind:focus { outline: none; }
.kvyk-step-picker__kind:focus-visible { box-shadow: inset var(--kvyk-ring); }
.kvyk-step-picker__words { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.kvyk-flow__loop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--kvyk-space-sm);
  width: 100%;
  margin-top: var(--_gap);
  padding: var(--kvyk-space-md);
  border: 2px dashed var(--_line);
  border-radius: var(--kvyk-radius-lg);
}
/* A step's own failure branch (.kvyk-flow__fails, right under its box): the
   step's line runs on down the middle while a red line turns off it to the
   right, an offset away, and leads down the branch (.kvyk-flow__fails-path):
   its label, its steps, and a label for where it goes on to
   (.kvyk-flow__then), red as the line. A last step's line stops there, but in
   a branch, whose line runs on to where the branches join. While editing, a
   step without a branch shows only its red plus there. On a phone the branch
   takes the line's place, between the step and the next one. */
.kvyk-flow__fails {
  --_offset: var(--kvyk-space-lg);
  --_trunk: var(--_line);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  width: 100%;
  background: linear-gradient(var(--_trunk), var(--_trunk)) center / 2px 100% no-repeat;
}
.kvyk-flow__step:last-child > .kvyk-flow__fails:last-child { --_trunk: transparent; }
.kvyk-flow__branch > .kvyk-flow > .kvyk-flow__step:last-child > .kvyk-flow__fails:last-child { --_trunk: var(--_line); }
.kvyk-flow__fails-path {
  --_line: var(--kvyk-error);
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  grid-column: 2;
  justify-self: start;
  width: min(100% - var(--_offset), 26rem);
  margin-left: var(--_offset);
  padding-top: var(--_gap);
  background: linear-gradient(var(--_line), var(--_line)) center top / 2px var(--_gap) no-repeat;
}
.kvyk-flow__fails-path::before {
  content: "";
  position: absolute;
  top: 0;
  left: calc(-1 * var(--_offset) - 1px);
  right: calc(50% - 1px);
  height: 2px;
  background: var(--_line);
}
.kvyk-flow__fails-path > .kvyk-flow__label,
.kvyk-flow__then > .kvyk-flow__label {
  background: var(--kvyk-error-container);
  color: var(--kvyk-on-error-container);
}
.kvyk-flow__fails-path > .kvyk-flow > .kvyk-flow__step > .kvyk-flow__add {
  border-color: var(--kvyk-error);
  color: var(--kvyk-error);
}
.kvyk-flow__then {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--kvyk-space-2xs);
  padding-top: var(--_gap);
  background: linear-gradient(var(--_line), var(--_line)) center top / 2px var(--_gap) no-repeat;
}
@media (max-width: 767px) {
  .kvyk-flow__fails { grid-template-columns: minmax(0, 1fr); background: none; }
  .kvyk-flow__fails-path { grid-column: 1; justify-self: center; width: min(100%, 26rem); margin-left: 0; }
  .kvyk-flow__fails-path::before { content: none; }
}
/* A run's path (--run): the lines it followed take the colour of a step done,
   into each step it reached and down each branch it took; a branch it did
   not take stays grey, its boxes faded, and so do the lines to steps it never
   reached. */
.kvyk-flow--run { --_taken: var(--kvyk-on-tertiary-container); }
.kvyk-flow--run .kvyk-flow__step.is-reached,
.kvyk-flow--run .kvyk-flow__branch.is-taken,
.kvyk-flow--run .kvyk-flow__branch.is-taken > .kvyk-flow { --_line: var(--_taken); }
.kvyk-flow--run .kvyk-flow__step:not(.is-reached),
.kvyk-flow--run .kvyk-flow__branch:not(.is-taken) { --_line: var(--kvyk-outline-variant); }
.kvyk-flow--run .kvyk-flow__branch:not(.is-taken) .kvyk-flow__box { opacity: 0.6; }
.kvyk-flow--run .kvyk-flow__fails.is-taken > .kvyk-flow__fails-path { --_line: var(--_taken); }
.kvyk-flow--run .kvyk-flow__fails:not(.is-taken) > .kvyk-flow__fails-path { --_line: var(--kvyk-outline-variant); }
.kvyk-flow--run .kvyk-flow__fails:not(.is-taken) .kvyk-flow__box { opacity: 0.6; }
/* An automation's When something fails path (--failure), drawn once under
   its flowchart (kvyk-flow-stack), so it takes none of the flowchart's width:
   a red line from its label down its steps. */
.kvyk-flow-stack {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--kvyk-space-md);
}
.kvyk-flow--failure { --_line: var(--kvyk-error); }
.kvyk-flow--failure > .kvyk-flow__step:first-child { gap: var(--kvyk-space-2xs); }
.kvyk-flow--failure > .kvyk-flow__step:first-child > .kvyk-flow__label {
  background: var(--kvyk-error-container);
  color: var(--kvyk-on-error-container);
}
/* On a phone the branches stack, each hanging from a line down their left:
   the step's line turns to it, it reaches each branch's label, and turns
   back below the last one to the next step. */
@media (max-width: 767px) {
  .kvyk-flow__branches {
    flex-direction: column;
    gap: var(--kvyk-space-md);
    padding: calc(2 * var(--_gap)) 0 calc(2 * var(--_gap)) var(--_gap);
    background:
      var(--_stroke) center top / 2px var(--_gap) no-repeat,
      var(--_stroke) left 0 top var(--_gap) / calc(50% + 1px) 2px no-repeat,
      var(--_stroke) left 0 top var(--_gap) / 2px calc(100% - 2 * var(--_gap)) no-repeat,
      var(--_stroke) left 0 bottom var(--_gap) / calc(50% + 1px) 2px no-repeat,
      var(--_stroke) center bottom / 2px var(--_gap) no-repeat;
  }
  .kvyk-flow__step:last-child > .kvyk-flow__branches:last-child {
    padding-bottom: calc(2 * var(--_gap));
    background-size: 2px var(--_gap), calc(50% + 1px) 2px, 2px calc(100% - 2 * var(--_gap)), calc(50% + 1px) 2px, 0 0;
  }
  .kvyk-flow__branch {
    align-items: flex-start;
    gap: var(--kvyk-space-sm);
    min-width: 0;
    padding-top: 0;
    background: none;
  }
  .kvyk-flow__branch::after { content: none; }
  .kvyk-flow__branch::before,
  .kvyk-flow__branch:first-child::before,
  .kvyk-flow__branch:last-child::before {
    top: calc(var(--kvyk-space-2xs) + 0.5lh);
    left: calc(-1 * var(--_gap));
    right: auto;
    width: var(--_gap);
  }
  .kvyk-flow__branch > :is(.kvyk-flow, .kvyk-flow__empty) { align-self: stretch; }
  .kvyk-flow__branch > .kvyk-flow__empty { align-items: flex-start; }
  .kvyk-flow__branch > :is(.kvyk-flow, .kvyk-flow__empty)::before,
  .kvyk-flow__branch > :is(.kvyk-flow, .kvyk-flow__empty)::after { content: none; }
}

/* ---- Template editor ------------------------------------------------------
   A document or email template written on a page: the editor beside its
   preview (.kvyk-template-layout, stacked below 1024px), or one of the two
   alone (--single), as the view chosen over them. Each text block has
   a .kvyk-template-toolbar of icon buttons, each in a .kvyk-tooltip--below naming
   it, over its .kvyk-template-editor__page; a section
   or a table of linked records is a .kvyk-template-frame with a bar naming
   it; a field to fill in is a .kvyk-template-chip, the organisation's logo a
   .kvyk-template-logo, and text in its brand colour a .kvyk-template-accent.
   An uploaded picture is a .kvyk-template-image in an image frame, aligned by
   its data-align; a table of the maker's own cells is a .kvyk-template-grid,
   its first row bold while data-header is "true". The text colours to choose
   from are .kvyk-template-swatch buttons in a .kvyk-template-swatches row.
   The organisation's colour comes in as --kvyk-template-brand. A block the
   assistant just changed is .is-changed. */
.kvyk-template-layout {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: var(--kvyk-space-lg);
  align-items: start;
}
@media (max-width: 1023px) {
  .kvyk-template-layout { grid-template-columns: minmax(0, 1fr); }
}
/* Only the editor or only the preview, as the view chosen over them. */
.kvyk-template-layout--single { grid-template-columns: minmax(0, 1fr); }
.kvyk-template-editor {
  display: flex;
  flex-direction: column;
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
}
.kvyk-template-editor:focus-within { border-color: var(--kvyk-secondary); box-shadow: var(--kvyk-ring); }
.kvyk-template-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px;
  padding: var(--kvyk-space-xs);
  border-bottom: 1px solid var(--kvyk-outline-variant);
  background: var(--kvyk-surface-container-low);
}
/* A toggle that is on where the cursor stands, such as Bold. */
.kvyk-template-toolbar .kvyk-btn[aria-pressed="true"] {
  background: var(--kvyk-secondary-fixed);
  color: var(--kvyk-on-secondary-fixed);
}
.kvyk-template-toolbar__gap {
  width: 1px;
  align-self: stretch;
  margin: 2px;
  background: var(--kvyk-outline-variant);
}
/* Compact, so the whole toolbar fits on one line beside the preview from
   1280px; on a narrower editor it wraps a __group at a time. */
.kvyk-template-toolbar .kvyk-btn--icon.kvyk-btn--sm { width: 28px; height: 28px; }
.kvyk-template-toolbar .kvyk-btn--icon .kvyk-icon { width: 18px; height: 18px; }
.kvyk-template-toolbar__group { display: flex; align-items: center; gap: 2px; }
/* The text style menu: each style shown as it reads in the text, the one
   where the cursor stands marked aria-pressed="true". */
.kvyk-template-styles { display: flex; flex-direction: column; gap: 2px; }
.kvyk-template-styles__option {
  display: block;
  width: 100%;
  padding: var(--kvyk-space-xs) var(--kvyk-space-sm);
  border: 0;
  border-radius: var(--kvyk-radius-sm);
  background: transparent;
  color: var(--kvyk-on-surface);
  font-family: var(--kvyk-font-sans);
  font-size: 14px;
  line-height: var(--kvyk-leading-heading);
  text-align: start;
  cursor: pointer;
}
.kvyk-template-styles__option:hover { background: var(--kvyk-surface-container-high); }
.kvyk-template-styles__option:focus-visible { outline: none; box-shadow: var(--kvyk-ring); }
.kvyk-template-styles__option[aria-pressed="true"] {
  background: var(--kvyk-secondary-fixed);
  color: var(--kvyk-on-secondary-fixed);
}
.kvyk-template-styles__option--heading-1,
.kvyk-template-styles__option--heading-2,
.kvyk-template-styles__option--heading-3 { font-weight: var(--kvyk-weight-semibold); }
.kvyk-template-styles__option--heading-1 { font-size: 32px; letter-spacing: -0.01em; }
.kvyk-template-styles__option--heading-2 { font-size: 24px; }
.kvyk-template-styles__option--heading-3 { font-size: 20px; }
/* The text fills the page, padding and all, so a click anywhere on it
   writes; the editor's own border shows focus, and the text no ring of
   its own. */
.kvyk-template-editor__page { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.kvyk-template-editor__text {
  flex: 1;
  width: 100%;
  box-sizing: border-box;
  min-height: 12rem;
  padding: var(--kvyk-space-lg);
  outline: none;
  font-size: 14px;
  line-height: var(--kvyk-leading-body);
  color: var(--kvyk-on-surface);
}
.kvyk-template-editor__text:focus,
.kvyk-template-editor__text:focus-visible { outline: none; box-shadow: none; }
.kvyk-template-editor--line .kvyk-template-editor__text { min-height: 0; padding: var(--kvyk-space-sm) var(--kvyk-space-md); }
/* A text of several lines is made taller or shorter from its corner, and
   scrolls inside once it is shorter than what it holds. */
.kvyk-template-editor:not(.kvyk-template-editor--line) .kvyk-template-editor__page { resize: vertical; overflow: auto; min-height: 12rem; }
/* --fill takes the height its parent gives it, as in a dialog over the page. */
.kvyk-field:has(> .kvyk-template-editor--fill) { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.kvyk-template-editor--fill { flex: 1; min-height: 0; }
.kvyk-template-editor--fill:not(.kvyk-template-editor--line) .kvyk-template-editor__page { resize: none; flex: 1; min-height: 0; }
.kvyk-template-editor__text > * + * { margin-top: var(--kvyk-space-sm); }
.kvyk-template-editor__text .is-changed {
  background: color-mix(in srgb, var(--kvyk-secondary-fixed) 45%, transparent);
  box-shadow: -3px 0 0 var(--kvyk-secondary);
}
.kvyk-template-frame {
  margin: var(--kvyk-space-sm) 0;
  border: 1px dashed var(--kvyk-outline);
  border-radius: var(--kvyk-radius-card);
}
.kvyk-template-frame--table { border-style: solid; background: var(--kvyk-surface-container-low); }
.kvyk-template-frame__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--kvyk-space-sm);
  padding: var(--kvyk-space-xs) var(--kvyk-space-xs) var(--kvyk-space-xs) var(--kvyk-space-sm);
  border-bottom: 1px solid var(--kvyk-outline-variant);
  user-select: none;
}
.kvyk-template-frame__label {
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-template-frame__body { padding: var(--kvyk-space-sm) var(--kvyk-space-md); }
.kvyk-template-frame__columns {
  margin: 0;
  padding: var(--kvyk-space-sm) var(--kvyk-space-md);
  font-size: 13px;
  color: var(--kvyk-on-surface-variant);
}
/* A field to fill in reads in its text's own style: a heading's size, bold or
   italic, its colour, only marked by its tint. */
.kvyk-template-chip {
  display: inline;
  padding: 0 0.3em;
  font: inherit;
  color: inherit;
  background: var(--kvyk-secondary-fixed);
  border-radius: var(--kvyk-radius-sm);
  white-space: nowrap;
}
.kvyk-template-chip.ProseMirror-selectednode { box-shadow: var(--kvyk-ring); }
.kvyk-template-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 160px;
  height: 56px;
  font-size: 12px;
  color: var(--kvyk-template-brand, var(--kvyk-secondary));
  border: 1px dashed var(--kvyk-template-brand, var(--kvyk-secondary));
  border-radius: var(--kvyk-radius-sm);
  user-select: none;
}
.kvyk-template-logo[data-align="center"] { margin-inline: auto; }
.kvyk-template-logo[data-align="end"] { margin-inline-start: auto; }
.kvyk-template-accent { color: var(--kvyk-template-brand, var(--kvyk-secondary)); }
.kvyk-template-image { display: flex; padding: var(--kvyk-space-sm) var(--kvyk-space-md); }
.kvyk-template-image[data-align="center"] { justify-content: center; }
.kvyk-template-image[data-align="end"] { justify-content: flex-end; }
.kvyk-template-image img { max-width: 100%; height: auto; }
/* An image with a corner dragged sideways to change its width, in its own
   block or standing in a table cell's text. */
.kvyk-template-image__holder,
.kvyk-template-cell-image { position: relative; display: inline-block; max-width: 100%; min-width: 0; line-height: 0; }
.kvyk-template-cell-image { vertical-align: middle; }
.kvyk-template-cell-image img { max-width: 100%; height: auto; cursor: pointer; }
.kvyk-template-resize {
  position: absolute;
  inset-inline-end: -5px;
  bottom: -5px;
  width: 10px;
  height: 10px;
  border: 2px solid var(--kvyk-surface-container-lowest);
  border-radius: var(--kvyk-radius-xs);
  background: var(--kvyk-secondary);
  cursor: nwse-resize;
  opacity: 0;
  transition: opacity var(--kvyk-duration) var(--kvyk-ease);
}
:is(.kvyk-template-image__holder, .kvyk-template-cell-image):hover .kvyk-template-resize,
.ProseMirror-selectednode .kvyk-template-resize,
.ProseMirror-selectednode.kvyk-template-cell-image .kvyk-template-resize { opacity: 1; }
.kvyk-template-grid { width: 100%; border-collapse: collapse; }
.kvyk-template-grid :is(td, th) {
  padding: var(--kvyk-space-xs) var(--kvyk-space-sm);
  border: 1px dashed var(--kvyk-outline-variant);
  text-align: start;
  vertical-align: top;
  font-weight: inherit;
}
.kvyk-template-grid[data-header="true"] tr:first-child > * { font-weight: var(--kvyk-weight-semibold); }
.kvyk-template-swatches { display: flex; flex-wrap: wrap; gap: var(--kvyk-space-xs); }
.kvyk-template-swatch {
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-sm);
  cursor: pointer;
}
.kvyk-template-swatch:focus-visible { outline: none; box-shadow: var(--kvyk-ring); }
.kvyk-template-swatch[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--kvyk-surface), 0 0 0 4px var(--kvyk-secondary); }
.kvyk-template-divider {
  margin: var(--kvyk-space-md) 0;
  border: 0;
  border-top: 1px solid var(--kvyk-outline-variant);
}
/* The lines a table shows, each kind named in its data-lines, solid in its
   border colour; the lines it does not show stay dashed in the editor so
   the cells can be seen. Without data-lines it shows the lines between rows. */
.kvyk-template-grid { --kvyk-template-line: 1px solid var(--kvyk-template-border, var(--kvyk-outline)); }
.kvyk-template-grid:not([data-lines]) tr + tr > *,
.kvyk-template-grid[data-lines~="innerHorizontal"] tr + tr > * { border-top: var(--kvyk-template-line); }
.kvyk-template-grid[data-lines~="outerHorizontal"] tr:first-child > * { border-top: var(--kvyk-template-line); }
.kvyk-template-grid[data-lines~="outerHorizontal"] tr:last-child > * { border-bottom: var(--kvyk-template-line); }
.kvyk-template-grid[data-lines~="outerVertical"] tr > :first-child { border-inline-start: var(--kvyk-template-line); }
.kvyk-template-grid[data-lines~="outerVertical"] tr > :last-child { border-inline-end: var(--kvyk-template-line); }
.kvyk-template-grid[data-lines~="innerVertical"] tr > * + * { border-inline-start: var(--kvyk-template-line); }
.kvyk-template-chip--slot { border-style: dashed; background: transparent; }
.kvyk-template-link { color: var(--kvyk-template-brand, var(--kvyk-secondary)); text-decoration: underline; }
/* A button block as it shows, in its background and text colours. */
.kvyk-template-button {
  display: inline-block;
  margin: var(--kvyk-space-sm) var(--kvyk-space-md);
  padding: var(--kvyk-space-xs) var(--kvyk-space-md);
  border-radius: var(--kvyk-radius-sm);
  background: var(--kvyk-template-brand, var(--kvyk-secondary));
  color: var(--kvyk-on-secondary);
  font-weight: var(--kvyk-weight-semibold);
}
.kvyk-template-list { margin: 0; padding-inline-start: var(--kvyk-space-lg); }
.kvyk-template-list li[data-level="1"] { margin-inline-start: var(--kvyk-space-lg); }
.kvyk-template-frame--section,
.kvyk-template-frame--columns { border-style: solid; }
.kvyk-template-frame--spacer .kvyk-template-frame__body,
.kvyk-template-frame--page-break .kvyk-template-frame__body { padding-block: var(--kvyk-space-xs); }
.kvyk-template-frame--page-break { border-style: dashed; border-width: 1px 0; border-radius: 0; }
.kvyk-template-frame--image .kvyk-template-frame__body { padding: 0; }
.kvyk-template-otherwise {
  margin: var(--kvyk-space-sm) var(--kvyk-space-md) var(--kvyk-space-md);
  border: 1px dashed var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-sm);
}
/* The columns of a columns block, side by side as many as its data-count. */
.kvyk-template-columns {
  display: grid;
  grid-template-columns: repeat(var(--kvyk-template-count, 2), minmax(0, 1fr));
  gap: var(--kvyk-space-sm);
  padding: var(--kvyk-space-sm) var(--kvyk-space-md);
}
.kvyk-template-columns[data-count="3"] { --kvyk-template-count: 3; }
.kvyk-template-columns[data-count="4"] { --kvyk-template-count: 4; }
.kvyk-template-column {
  min-width: 0;
  min-height: 2.5rem;
  padding: var(--kvyk-space-xs) var(--kvyk-space-sm);
  border: 1px dashed var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-sm);
}
/* The grip before each block: it shows while the pointer is over the text,
   and stays where the block starts because it is out of the flow. */
.kvyk-template-editor__text { position: relative; }
.kvyk-template-handle {
  position: absolute;
  inset-inline-start: 2px;
  width: 12px;
  height: 20px;
  margin-top: 2px;
  cursor: grab;
  opacity: 0;
  background-image: radial-gradient(circle, var(--kvyk-on-surface-variant) 1px, transparent 1.5px);
  background-size: 6px 6px;
  transition: opacity var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-template-editor__text:hover .kvyk-template-handle { opacity: 0.6; }
.kvyk-template-handle:hover { opacity: 1; }
.kvyk-template-handle { user-select: none; }
/* Level with the block's first line: past the space above the block, then
   half the line's height beyond its own. */
.kvyk-template-editor__text > * + .kvyk-template-handle { margin-top: calc(var(--kvyk-space-sm) + 1px); }
.kvyk-template-handle:has(+ h1) { translate: 0 9px; }
.kvyk-template-handle:has(+ h2) { translate: 0 4px; }
.kvyk-template-handle:has(+ h3) { translate: 0 2px; }
/* The chosen block's handle stays shown, and darker. */
.kvyk-template-handle:has(+ .ProseMirror-selectednode) {
  opacity: 1;
  background-image: radial-gradient(circle, var(--kvyk-on-surface) 1.5px, transparent 2px);
}
/* The text size menu: a size typed in points, the normal size, then the
   usual sizes, the one where the cursor stands marked aria-pressed="true". */
.kvyk-size-picker__button { min-width: 3.5rem; justify-content: space-between; }
.kvyk-size-picker { display: flex; flex-direction: column; gap: var(--kvyk-space-sm); min-width: 13rem; }
.kvyk-size-picker__typed { display: flex; gap: var(--kvyk-space-xs); }
.kvyk-size-picker__typed .kvyk-input { width: 5rem; }
.kvyk-size-picker__options { display: flex; flex-direction: column; gap: 2px; max-height: 14rem; overflow-y: auto; }
.kvyk-size-picker__option {
  padding: var(--kvyk-space-xs) var(--kvyk-space-sm);
  border: 0;
  border-radius: var(--kvyk-radius-sm);
  background: transparent;
  color: var(--kvyk-on-surface);
  font-family: var(--kvyk-font-sans);
  font-size: 14px;
  text-align: start;
  cursor: pointer;
}
.kvyk-size-picker__option:hover { background: var(--kvyk-surface-container-high); }
.kvyk-size-picker__option:focus-visible { outline: none; box-shadow: var(--kvyk-ring); }
.kvyk-size-picker__option[aria-pressed="true"] { background: var(--kvyk-secondary-fixed); color: var(--kvyk-on-secondary-fixed); }
/* A table's layout: a row of icon buttons, the same as the toolbar's. */
.kvyk-template-grid-tools { display: flex; flex-wrap: wrap; gap: 2px; }
.kvyk-template-grid-tools .kvyk-btn[aria-pressed="true"] { background: var(--kvyk-secondary-fixed); color: var(--kvyk-on-secondary-fixed); }
/* Which of a table's lines show, as in a spreadsheet: a toggle for each
   kind, drawn as the lines it turns on, pressed while they show. */
.kvyk-border-picker { display: flex; gap: var(--kvyk-space-xs); }
.kvyk-border-picker__side {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-sm);
  background: var(--kvyk-surface-container-lowest);
  color: var(--kvyk-on-surface-variant);
  cursor: pointer;
}
.kvyk-border-picker__side:hover { background: var(--kvyk-surface-container-high); }
.kvyk-border-picker__side:focus-visible { outline: none; box-shadow: var(--kvyk-ring); }
.kvyk-border-picker__side[aria-pressed="true"] {
  border-color: var(--kvyk-secondary);
  background: var(--kvyk-secondary-fixed);
  color: var(--kvyk-on-secondary-fixed);
}
.kvyk-template-menu__item { justify-content: flex-start; width: 100%; }
/* A colour chosen from the organisation's colours, the recent ones, a grid
   with a column per hue from light to dark, or typed as a code. */
.kvyk-color-picker { display: flex; flex-direction: column; gap: var(--kvyk-space-sm); min-width: 15rem; }
.kvyk-color-picker__row { display: flex; flex-direction: column; gap: var(--kvyk-space-xs); }
.kvyk-color-picker__heading { font-size: 12px; line-height: 16px; color: var(--kvyk-on-surface-variant); }
.kvyk-color-picker__grid { display: grid; grid-template-rows: repeat(6, 28px); grid-auto-flow: column; grid-auto-columns: 28px; gap: var(--kvyk-space-xs); }
.kvyk-color-picker__system { width: 36px; height: 36px; padding: 0; border: 1px solid var(--kvyk-outline-variant); border-radius: var(--kvyk-radius-sm); cursor: pointer; }
.kvyk-color-picker__hex.kvyk-input { width: 7rem; }
.kvyk-color-field { display: inline-flex; align-items: center; gap: var(--kvyk-space-xs); }
.kvyk-color-field__swatch {
  width: 16px;
  height: 16px;
  flex: none;
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-xs);
  background-image: linear-gradient(135deg, transparent 45%, var(--kvyk-outline-variant) 45% 55%, transparent 55%);
}
.kvyk-color-field__swatch[style] { background-image: none; }
/* The versions of a template, newest first, each one chosen to view it. */
.kvyk-template-versions__list { margin: 0; padding: 0; list-style: none; max-height: 16rem; overflow-y: auto; }
.kvyk-template-versions__item { justify-content: flex-start; width: 100%; }
/* A template's language bar, on one row: the language picker, its state
   badges, then its actions at the far end. On a phone the actions wrap
   under the rest. */
.kvyk-language-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--kvyk-space-sm); }
.kvyk-language-bar__badges { display: flex; flex-wrap: nowrap; align-items: center; gap: var(--kvyk-space-xs); white-space: nowrap; }
.kvyk-language-bar__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--kvyk-space-xs); margin-inline-start: auto; }
@media (max-width: 479px) {
  .kvyk-language-bar__actions { margin-inline-start: 0; width: 100%; }
}
/* A text editor's label with something beside it, such as Full screen. */
.kvyk-template-editor__head { display: flex; align-items: center; justify-content: space-between; gap: var(--kvyk-space-sm); min-width: 0; }
/* A titled group of settings in a settings card: page, look, keeping. */
.kvyk-settings-group { --_flow-gap: var(--kvyk-space-sm-md); display: flex; flex-direction: column; gap: var(--_flow-gap); min-width: 0; }
.kvyk-settings-group + .kvyk-settings-group { padding-top: var(--kvyk-space-md); border-top: 1px solid var(--kvyk-outline-variant); }
.kvyk-settings-group > .kvyk-overline { margin: 0; }
/* A small page in a segmented item: upright for portrait, --landscape on its side. */
.kvyk-page-shape { display: inline-block; flex: none; width: 10px; height: 14px; border: 1.5px solid currentColor; border-radius: 1px; }
.kvyk-page-shape--landscape { width: 14px; height: 10px; }
/* A page's four margins, each on its side of a pictured page (__page). */
.kvyk-margins {
  display: grid;
  grid-template-columns: auto 72px auto;
  grid-template-rows: auto 96px auto;
  grid-template-areas: ". top ." "left page right" ". bottom .";
  align-items: center;
  justify-items: center;
  gap: var(--kvyk-space-sm);
  width: max-content;
  max-width: 100%;
}
.kvyk-margins--landscape { grid-template-columns: auto 96px auto; grid-template-rows: auto 72px auto; }
.kvyk-margins__side { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.kvyk-margins__side--top { grid-area: top; }
.kvyk-margins__side--right { grid-area: right; }
.kvyk-margins__side--bottom { grid-area: bottom; }
.kvyk-margins__side--left { grid-area: left; }
.kvyk-margins__side .kvyk-input--narrow { width: 5rem; }
.kvyk-margins__page {
  grid-area: page;
  width: 100%;
  height: 100%;
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline);
  border-radius: var(--kvyk-radius-xs);
  box-shadow: inset 0 0 0 10px var(--kvyk-surface-container-low);
}
@media (max-width: 479px) {
  .kvyk-margins { grid-template-columns: auto 48px auto; grid-template-rows: auto 64px auto; }
}
/* A thumbnail of the image behind a document's pages. */
.kvyk-page-thumb { display: block; width: 96px; height: 128px; object-fit: cover; border: 1px solid var(--kvyk-outline-variant); border-radius: var(--kvyk-radius-xs); background: var(--kvyk-surface-container-low); }
/* How a background image fills a page, pictured: a page with the image as a
   filled shape inside it, fitted, stretched, filling it or tiled. */
.kvyk-fit-shape {
  position: relative;
  display: inline-block;
  flex: none;
  width: 12px;
  height: 16px;
  border: 1.5px solid currentColor;
  border-radius: 1px;
  overflow: hidden;
}
.kvyk-fit-shape::before { content: ""; position: absolute; background: currentColor; opacity: 0.45; }
.kvyk-fit-shape--contain::before { left: 0; right: 0; top: 4px; bottom: 4px; }
.kvyk-fit-shape--stretch::before { inset: 0; }
.kvyk-fit-shape--cover::before { inset: -2px -4px; opacity: 0.7; }
.kvyk-fit-shape--tile::before {
  inset: 0;
  opacity: 1;
  background: repeating-conic-gradient(currentColor 0 25%, transparent 0 50%) 0 0 / 6px 6px;
}
/* A segmented control whose items wrap to more rows instead of running past its container. */
.kvyk-segmented.kvyk-segmented--wrap { flex-wrap: wrap; max-width: 100%; }
.kvyk-template-preview {
  position: sticky;
  top: var(--kvyk-space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-sm);
}
.kvyk-template-preview__frame {
  width: 100%;
  height: 480px;
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  background: var(--kvyk-surface-container-lowest);
}
.kvyk-template-preview__frame--page { height: auto; aspect-ratio: 210 / 297; }
/* A page shown at its own size in mm, zoomed; wider than the column it scrolls. */
.kvyk-template-preview__pages { overflow: auto; max-height: 80vh; }
.kvyk-template-preview__pages .kvyk-template-preview__frame--page { display: block; max-width: none; aspect-ratio: auto; margin-inline: auto; }
@media (max-width: 1023px) {
  .kvyk-template-preview { position: static; }
}

/* ---- Keep or undo bar ------------------------------------------------------
   What the assistant just changed in an open editor, over it, with Keep and
   Undo. What it changed stands out (.is-changed) until one of the two. */
.kvyk-keep-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--kvyk-space-sm) var(--kvyk-space-md);
  padding: var(--kvyk-space-sm) var(--kvyk-space-sm) var(--kvyk-space-sm) var(--kvyk-space-md);
  background: var(--kvyk-secondary-fixed);
  color: var(--kvyk-on-secondary-fixed);
  border-left: 3px solid var(--kvyk-secondary);
}
.kvyk-keep-bar__text { margin: 0; font-size: 14px; }
.kvyk-keep-bar__actions { display: flex; gap: var(--kvyk-space-sm); }

/* ---- Field / Input / Textarea / Select ----------------------------------- */
.kvyk-field {
  --_flow-gap: var(--kvyk-space-sm);
  display: flex;
  flex-direction: column;
  gap: var(--_flow-gap);
}
/* A field of several controls is a fieldset under a legend: it keeps the
   field's look, not the browser's framed box. */
fieldset.kvyk-field {
  margin: 0;
  padding: 0;
  border: 0;
  min-inline-size: 0;
}
legend.kvyk-label {
  padding: 0;
  margin-bottom: var(--kvyk-space-sm);
}
/* A group of controls under a legend, without the browser's frame. */
.kvyk-fieldset {
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.kvyk-label {
  font-family: var(--kvyk-font-mono);
  font-size: 14px;
  line-height: 20px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.02em;
  color: var(--kvyk-on-surface);
}
/* A hint under a field or an option: a step below its label in size and tone, so the label leads. */
.kvyk-help { font-size: 13px; line-height: 18px; color: color-mix(in srgb, var(--kvyk-on-surface-variant) 55%, var(--kvyk-outline)); }
.kvyk-error-text {
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  line-height: 16px;
  color: var(--kvyk-error);
}
/* A label with something beside it, such as the question mark of a tip on
   what the setting means. */
.kvyk-field__head { display: flex; align-items: center; gap: var(--kvyk-space-xs); }
/* A field whose problem is said below it: its controls are marked as an
   input with aria-invalid is, without each control saying so itself. */
.kvyk-field.is-invalid :is(.kvyk-input, .kvyk-textarea, .kvyk-select) { border-color: var(--kvyk-error); }

.kvyk-input,
.kvyk-textarea,
.kvyk-select {
  width: 100%;
  font-family: var(--kvyk-font-sans);
  font-size: 16px;
  line-height: 24px;
  color: var(--kvyk-on-surface);
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-sm);
  padding: var(--kvyk-space-sm) var(--kvyk-space-sm-md);
  transition: border-color var(--kvyk-duration) var(--kvyk-ease),
              box-shadow var(--kvyk-duration) var(--kvyk-ease),
              background-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-input::placeholder,
.kvyk-textarea::placeholder { color: var(--kvyk-on-surface-variant); opacity: 0.6; }
/* One height for every single-line control, so a field and its button line up. */
.kvyk-input,
.kvyk-select { height: var(--kvyk-control-height); padding-block: 0; }
.kvyk-input:hover:not(:focus):not(:disabled),
.kvyk-textarea:hover:not(:focus):not(:disabled),
.kvyk-select:hover:not(:focus):not(:disabled) { border-color: var(--kvyk-outline); }

.kvyk-input:focus,
.kvyk-textarea:focus,
.kvyk-select:focus {
  outline: none;
  border-color: var(--kvyk-secondary);
  box-shadow: 0 0 0 3px var(--kvyk-ring-color);
}
.kvyk-textarea { resize: vertical; min-height: 80px; }

.kvyk-input[aria-invalid="true"],
.kvyk-textarea[aria-invalid="true"],
.kvyk-select[aria-invalid="true"],
.kvyk-input.is-invalid {
  border-color: var(--kvyk-error);
}
.kvyk-input[aria-invalid="true"]:focus,
.kvyk-textarea[aria-invalid="true"]:focus,
.kvyk-select[aria-invalid="true"]:focus,
.kvyk-input.is-invalid:focus {
  box-shadow: 0 0 0 3px rgba(186, 26, 26, 0.25);
}
.kvyk-input:disabled,
.kvyk-textarea:disabled,
.kvyk-select:disabled { opacity: 0.5; cursor: not-allowed; }

/* A short value, such as a number or a colour code, beside its label. */
.kvyk-input.kvyk-input--narrow { width: 8rem; }
/* A PIN or a short code typed on a shared device: big, spaced digits. */
.kvyk-input.kvyk-input--pin {
  height: 56px;
  font-family: var(--kvyk-font-mono);
  font-size: 24px;
  letter-spacing: 0.3em;
  text-align: center;
}
.kvyk-input.kvyk-input--sm { padding: var(--kvyk-space-xs) var(--kvyk-space-sm); font-size: 14px; line-height: 20px; }

/* A name changed where it stands, as a page's title: it reads as the
   heading it sits in, and shows it is a field on hover and on focus. Its
   text lines up with the heading's edge. */
.kvyk-input.kvyk-input--title {
  height: auto;
  padding: 2px var(--kvyk-space-sm);
  margin-inline-start: calc(-1 * var(--kvyk-space-sm) - 1px);
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  background: transparent;
  border-color: transparent;
}
.kvyk-input.kvyk-input--title:hover { border-color: var(--kvyk-outline-variant); }
.kvyk-input.kvyk-input--title:focus {
  background: var(--kvyk-surface-container-lowest);
  border-color: var(--kvyk-secondary);
}

/* Native select with a custom chevron */
.kvyk-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 40px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%2345464d'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M6%209l6%206%206-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 20px;
}
/* A compact select, as tall as a small button and as wide as its options. */
.kvyk-select.kvyk-select--sm {
  width: auto;
  height: var(--kvyk-control-height-sm);
  padding: 0 32px 0 var(--kvyk-space-sm);
  font-size: 14px;
  line-height: 30px;
  background-position: right 8px center;
  background-size: 16px;
}

/* A searchable choice, for lists too long for a native select: the input
   filters, and a listbox of the matches opens under it (the ARIA combobox
   pattern). The active option takes the selected surface.
   The list is a manual popover (`popover="manual"`, shown with
   showPopover()): it floats in the browser's top layer, above a modal
   dialog too, so nothing around it grows or clips it. The script places it
   with fixed coordinates under its input, as wide as it, or above it when
   there is no room below, and sets its max-height to the room it has. */
.kvyk-combobox { position: relative; min-width: 14rem; }
.kvyk-combobox > .kvyk-input { width: 100%; }
/* As tall as a small button and a .kvyk-select--sm: for a toolbar. */
.kvyk-combobox--sm > .kvyk-input { height: var(--kvyk-control-height-sm); font-size: 14px; }
.kvyk-combobox__list {
  position: fixed;
  inset: auto;
  z-index: calc(var(--kvyk-z-header) + 5);
  box-sizing: border-box;
  height: auto;
  max-height: 18rem;
  overflow-y: auto;
  margin: 0;
  padding: var(--kvyk-space-xs);
  list-style: none;
  color: var(--kvyk-on-surface);
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-sm);
  box-shadow: var(--kvyk-elevation-2);
}
.kvyk-combobox__option {
  padding: var(--kvyk-space-xs) var(--kvyk-space-sm);
  font-size: 14px;
  line-height: 20px;
  color: var(--kvyk-on-surface);
  border-radius: var(--kvyk-radius-sm);
  cursor: pointer;
}
.kvyk-combobox__option[aria-selected="true"] {
  background: var(--kvyk-surface-selected);
}
/* A second name beside the option's, such as a language's own name. */
.kvyk-combobox__detail {
  margin-inline-start: var(--kvyk-space-sm);
  color: var(--kvyk-on-surface-variant);
}
.kvyk-combobox__status {
  padding: var(--kvyk-space-xs) var(--kvyk-space-sm);
  font-size: 13px;
  line-height: 18px;
  color: var(--kvyk-on-surface-variant);
}

/* Input with a leading icon, a trailing icon button, or both: wrap in
   .kvyk-input-group. The leading icon is a direct child; the button is
   .kvyk-input-group__action (an icon-only .kvyk-btn--icon.kvyk-btn--sm, such
   as showing what a password field holds). */
.kvyk-input-group { position: relative; display: flex; align-items: center; min-width: 0; }
.kvyk-input-group > .kvyk-icon {
  position: absolute;
  left: 12px;
  color: var(--kvyk-on-surface-variant);
  pointer-events: none;
}
.kvyk-input-group > .kvyk-icon ~ .kvyk-input { padding-left: 40px; }
.kvyk-input-group__action {
  position: absolute;
  right: 4px;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-input-group:has(> .kvyk-input-group__action) .kvyk-input { padding-right: 44px; }

/* ---- Checkbox / Radio ---------------------------------------------------- */
.kvyk-checkbox,
.kvyk-radio {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  margin: 0;
  background: var(--kvyk-surface-container-lowest);
  border: 2px solid var(--kvyk-outline);
  cursor: pointer;
  display: inline-grid;
  place-content: center;
  transition: border-color var(--kvyk-duration) var(--kvyk-ease),
              background-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-checkbox { border-radius: var(--kvyk-radius-xs); }
.kvyk-radio { border-radius: var(--kvyk-radius-circle); }

.kvyk-checkbox::before {
  content: "";
  width: 11px;
  height: 11px;
  transform: scale(0);
  transition: transform var(--kvyk-duration-fast) var(--kvyk-ease);
  background: var(--kvyk-on-secondary);
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
.kvyk-checkbox:checked {
  background: var(--kvyk-secondary);
  border-color: var(--kvyk-secondary);
}
.kvyk-checkbox:checked::before { transform: scale(1); }

.kvyk-radio::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: var(--kvyk-radius-circle);
  transform: scale(0);
  transition: transform var(--kvyk-duration-fast) var(--kvyk-ease);
  background: var(--kvyk-secondary);
}
.kvyk-radio:checked { border-color: var(--kvyk-secondary); }
.kvyk-radio:checked::before { transform: scale(1); }

.kvyk-checkbox:focus-visible,
.kvyk-radio:focus-visible { box-shadow: var(--kvyk-ring); }

/* Checkbox/radio + label row */
.kvyk-choice {
  display: inline-flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  cursor: pointer;
}
/* A choice on a row of fields lined up at their foot: as tall as their
   controls, so it sits on the same line as them. */
.kvyk-items-end > .kvyk-choice { min-height: var(--kvyk-control-height); }

/* ---- Switch -------------------------------------------------------------- */
.kvyk-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 40px;
  height: 22px;
  flex-shrink: 0;
}
.kvyk-switch input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}
.kvyk-switch__track {
  position: absolute;
  inset: 0;
  background: var(--kvyk-outline);
  border-radius: var(--kvyk-radius-pill);
  transition: background-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-switch__track::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  background: #fff;
  border-radius: var(--kvyk-radius-circle);
  box-shadow: var(--kvyk-elevation-1);
  transition: transform var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-switch input:checked + .kvyk-switch__track { background: var(--kvyk-secondary); }
.kvyk-switch input:checked + .kvyk-switch__track::before { transform: translateX(18px); }
.kvyk-switch input:focus-visible + .kvyk-switch__track { box-shadow: var(--kvyk-ring); }

/* ---- Selectable option card (radio styled as a panel) -------------------- */
.kvyk-option {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--kvyk-space-sm-md);
  padding: var(--kvyk-space-md);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  background: var(--kvyk-surface-container-lowest);
  cursor: pointer;
  transition: background-color var(--kvyk-duration) var(--kvyk-ease),
              border-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-option:hover { background: var(--kvyk-surface-hover); }
.kvyk-option:has(input:checked) { border-color: var(--kvyk-secondary); }
/* The option's words, its name over what it means, apart from each other. */
.kvyk-option > :not(input) {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-xs);
}

/* ---- Segmented control / Tabs ------------------------------------------- */
.kvyk-segmented {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  background: var(--kvyk-surface-container-low);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-md);
}
.kvyk-segmented__item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--kvyk-space-xs);
  padding: 6px 12px;
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.02em;
  color: var(--kvyk-on-surface-variant);
  background: transparent;
  border: none;
  border-radius: var(--kvyk-radius-sm);
  cursor: pointer;
  transition: background-color var(--kvyk-duration) var(--kvyk-ease),
              color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-segmented__item:hover { color: var(--kvyk-on-surface); }
/* In a toolbar on a phone, a segmented control keeps to the toolbar's width
   and its items share it, instead of running past the surface's edge. */
@media (max-width: 479px) {
  .kvyk-toolbar > .kvyk-segmented { max-width: 100%; }
  .kvyk-toolbar > .kvyk-segmented > .kvyk-segmented__item { flex: 1 1 auto; min-width: 0; padding-inline: 8px; }
}
/* A preview's device switch (Desktop, Tablet, Phone): on a phone the screen
   is the phone, and every device shows at its width, so the switch goes and
   leaves the toolbar room for the controls that still matter there. */
@media (max-width: 479px) {
  .kvyk-segmented--devices { display: none; }
}
.kvyk-segmented__item.is-untranslated::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: var(--kvyk-radius-circle);
  background: var(--kvyk-error);
}
.kvyk-segmented__item.is-active,
.kvyk-segmented__item[aria-selected="true"] {
  background: var(--kvyk-surface-container-lowest);
  color: var(--kvyk-on-surface);
  box-shadow: var(--kvyk-elevation-1);
}

.kvyk-tabs {
  display: flex;
  gap: var(--kvyk-space-lg);
  /* Baseline drawn as an inset shadow rather than a border so it never adds to the
     scrollable area — a border + the tabs' -1px overlap would push 1px past the
     content box and trip a phantom vertical scrollbar once this becomes a scroller. */
  box-shadow: inset 0 -1px 0 var(--kvyk-outline-variant);
  /* When tabs exceed the width they scroll instead of overflowing the parent.
     The scrollbar only appears once they don't fit, so wide layouts are unchanged. */
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--kvyk-outline-variant) transparent;
}
.kvyk-tabs::-webkit-scrollbar { height: 3px; }
.kvyk-tabs::-webkit-scrollbar-thumb {
  background: var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-pill);
}
.kvyk-tabs::-webkit-scrollbar-track { background: transparent; }
.kvyk-tab {
  flex: 0 0 auto; /* keep each tab's natural width; the strip scrolls rather than squashing tabs */
  scroll-snap-align: start;
  white-space: nowrap;
  padding: var(--kvyk-space-sm) 0;
  font-family: var(--kvyk-font-mono);
  font-size: 14px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.02em;
  color: var(--kvyk-on-surface-variant);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  transition: color var(--kvyk-duration) var(--kvyk-ease),
              border-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-tab:hover { color: var(--kvyk-on-surface); }
.kvyk-tab.is-active,
.kvyk-tab[aria-selected="true"] {
  color: var(--kvyk-secondary);
  border-bottom-color: var(--kvyk-secondary);
}

/* ---- Navigation (sidebar) ------------------------------------------------ */
.kvyk-nav { display: flex; flex-direction: column; gap: var(--kvyk-space-2xs); }
.kvyk-nav-item {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  padding: var(--kvyk-space-sm) var(--kvyk-space-sm-md);
  border-radius: var(--kvyk-radius-sm);
  font-family: var(--kvyk-font-mono);
  font-size: 14px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.02em;
  color: var(--kvyk-on-surface-variant);
  text-decoration: none;
  transition: background-color var(--kvyk-duration) var(--kvyk-ease),
              color var(--kvyk-duration) var(--kvyk-ease);
}
/* A nav item that acts rather than links (opening the assistant). */
button.kvyk-nav-item {
  width: 100%;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
}
.kvyk-nav-item:hover {
  background: var(--kvyk-surface-hover);
  color: var(--kvyk-on-surface);
  text-decoration: none;
}
/* The active item: the selected surface with full-strength text and icon.
   No accent: the nav never outshouts the page. */
.kvyk-nav-item.is-active,
.kvyk-nav-item[aria-current="page"],
.kvyk-nav-item.is-active:hover,
.kvyk-nav-item[aria-current="page"]:hover {
  background: var(--kvyk-surface-selected);
  color: var(--kvyk-on-surface);
}
/* Entries a level down, under the item that opens them. */
.kvyk-nav--nested { padding-left: var(--kvyk-space-lg); }
/* The item that leads the menu, apart from the pages under it: the
   assistant, in the accent, since it is how most work gets done. */
.kvyk-nav-item--accent,
.kvyk-nav-item--accent:hover { color: var(--kvyk-secondary); }
.kvyk-nav-item--accent { margin-bottom: var(--kvyk-space-sm); }
.kvyk-nav-item--accent:hover,
.kvyk-nav-item--accent.is-active,
.kvyk-nav-item--accent.is-active:hover {
  background: var(--kvyk-secondary-fixed);
  color: var(--kvyk-on-secondary-fixed-variant);
}

/* ---- Navigation (top bar links) ----------------------------------------- */
.kvyk-navlink {
  padding: var(--kvyk-space-xs) var(--kvyk-space-sm);
  border-radius: var(--kvyk-radius-sm);
  font-family: var(--kvyk-font-mono);
  font-size: 14px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.02em;
  color: var(--kvyk-on-surface-variant);
  text-decoration: none;
  transition: background-color var(--kvyk-duration) var(--kvyk-ease),
              color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-navlink:hover { background: var(--kvyk-surface-container-low); color: var(--kvyk-on-surface); text-decoration: none; }
.kvyk-navlink.is-active { color: var(--kvyk-on-surface); }

/* ---- Breadcrumbs --------------------------------------------------------- */
/* Where a page sits, in mono chrome: each step a link, the page itself plain. */
.kvyk-breadcrumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--kvyk-space-xs) var(--kvyk-space-sm);
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--kvyk-font-mono);
  font-size: 14px;
  line-height: 20px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.02em;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-breadcrumbs li {
  display: inline-flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  min-width: 0;
}
.kvyk-breadcrumbs li + li::before {
  content: "/";
  color: var(--kvyk-outline-variant);
}
.kvyk-breadcrumbs a,
.kvyk-breadcrumbs [aria-current="page"] {
  max-width: 24ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kvyk-breadcrumbs a { color: inherit; text-decoration: none; }
.kvyk-breadcrumbs a:hover { color: var(--kvyk-secondary); }
.kvyk-breadcrumbs [aria-current="page"] { color: var(--kvyk-on-surface); }

/* ---- Avatar -------------------------------------------------------------- */
.kvyk-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--kvyk-radius-circle);
  background: var(--kvyk-primary-container);
  color: var(--kvyk-on-primary-container);
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  font-weight: var(--kvyk-weight-medium);
  overflow: hidden;
  flex-shrink: 0;
}
.kvyk-avatar img { width: 100%; height: 100%; object-fit: cover; }
.kvyk-avatar--sm { width: 24px; height: 24px; }
.kvyk-avatar--lg { width: 40px; height: 40px; }
.kvyk-avatar--bordered { border: 1px solid var(--kvyk-outline-variant); }

/* ---- Brand lockup -------------------------------------------------------- */
.kvyk-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--kvyk-space-xs);
  font-family: var(--kvyk-font-sans);
  font-size: 24px;
  font-weight: var(--kvyk-weight-bold);
  letter-spacing: -0.01em;
  color: var(--kvyk-on-surface);
  text-decoration: none;
}
.kvyk-brand:hover { text-decoration: none; }
/* Sized to the brand name's cap height (~0.73em) plus the triangle's own padding
   inside its viewBox, so the mark lines up with the letters instead of overhanging.
   Nudged down slightly: the downward-pointing triangle reads high when centered, so
   this drops it to sit in line with the lowercase letters (the "v" in kvyk). */
.kvyk-brand__mark { width: 0.68em; height: 0.68em; transform: translateY(0.07em); }

/* ---- Stepper ------------------------------------------------------------- */
.kvyk-stepper {
  display: flex;
  align-items: flex-start;
}
.kvyk-step {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--kvyk-space-sm);
  text-align: center;
}
/* connector line, drawn from the previous step's marker */
.kvyk-step:not(:first-child)::before {
  content: "";
  position: absolute;
  top: 16px;
  right: 50%;
  left: -50%;
  height: 2px;
  background: var(--kvyk-outline-variant);
  z-index: 0;
}
.kvyk-step[data-state="complete"]:not(:first-child)::before,
.kvyk-step[data-state="active"]:not(:first-child)::before { background: var(--kvyk-secondary); }

.kvyk-step__marker {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--kvyk-radius-circle);
  border: 2px solid var(--kvyk-outline-variant);
  background: var(--kvyk-surface-container-lowest);
  color: var(--kvyk-outline);
  font-family: var(--kvyk-font-mono);
  font-size: 14px;
  font-weight: var(--kvyk-weight-medium);
}
.kvyk-step__label {
  font-family: var(--kvyk-font-sans);
  font-size: 13px;
  line-height: 18px;
  font-weight: var(--kvyk-weight-regular);
  color: var(--kvyk-on-surface-variant);
}
.kvyk-step[data-state="complete"] .kvyk-step__marker {
  background: var(--kvyk-secondary);
  border-color: var(--kvyk-secondary);
  color: var(--kvyk-on-secondary);
}
.kvyk-step[data-state="active"] .kvyk-step__marker {
  border-color: var(--kvyk-secondary);
  color: var(--kvyk-secondary);
  box-shadow: 0 0 0 4px rgba(0, 88, 190, 0.18);
}
.kvyk-step[data-state="active"] .kvyk-step__label { color: var(--kvyk-on-surface); font-weight: var(--kvyk-weight-semibold); }

/* ---- AI prompt bar ------------------------------------------------------- */
.kvyk-prompt {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  padding: var(--kvyk-space-sm);
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-lg);
  box-shadow: var(--kvyk-elevation-2);
  transition: border-color var(--kvyk-duration) var(--kvyk-ease),
              box-shadow var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-prompt:focus-within {
  border-color: var(--kvyk-secondary);
  box-shadow: 0 0 0 3px var(--kvyk-ring-color);
}
.kvyk-prompt__icon { color: var(--kvyk-secondary); padding-left: var(--kvyk-space-sm); }
.kvyk-prompt__input {
  flex: 1;
  min-width: 0; /* allow the input to shrink below its intrinsic size in narrow containers */
  height: 40px;
  border: none;
  background: transparent;
  font-family: var(--kvyk-font-sans);
  font-size: 18px;
  color: var(--kvyk-on-surface);
}
/* The bar shows focus via .kvyk-prompt:focus-within, so clear the input's own
   ring — the global :focus-visible paints a box-shadow, which outline:none misses. */
.kvyk-prompt__input:focus { outline: none; box-shadow: none; }
.kvyk-prompt__input::placeholder { color: var(--kvyk-on-surface-variant); opacity: 0.6; }

/* ---- Chat ---------------------------------------------------------------- */
.kvyk-chat { display: flex; flex-direction: column; gap: var(--kvyk-space-lg); }
.kvyk-bubble {
  max-width: 85%;
  overflow-wrap: break-word;
  padding: var(--kvyk-space-md);
  font-size: 14px;
  line-height: var(--kvyk-leading-body);
  border-radius: var(--kvyk-radius-lg);
}
.kvyk-bubble--user {
  align-self: flex-end;
  background: var(--kvyk-surface-container);
  color: var(--kvyk-on-surface);
  border: 1px solid var(--kvyk-outline-variant);
  border-top-right-radius: var(--kvyk-radius-xs);
}
.kvyk-bubble--ai {
  align-self: flex-start;
  background: var(--kvyk-surface-container-lowest);
  color: var(--kvyk-on-surface);
  border: 1px solid var(--kvyk-outline-variant);
  border-top-left-radius: var(--kvyk-radius-xs);
  box-shadow: var(--kvyk-elevation-1);
}
.kvyk-bubble__meta {
  font-family: var(--kvyk-font-mono);
  font-size: 11px;
  color: var(--kvyk-on-surface-variant);
  margin-top: var(--kvyk-space-xs);
}
/* What a message replies to, quoted at its start: quieter, after a rule. */
.kvyk-bubble__quote {
  margin: 0 0 var(--kvyk-space-xs);
  padding-left: var(--kvyk-space-sm);
  border-left: 2px solid var(--kvyk-outline-variant);
  color: var(--kvyk-on-surface-variant);
}

/* A prompt that grows with what is typed: Enter sends, Shift+Enter a new line.
   It grows up to eight lines (never past a third of the screen), then
   scrolls inside; the page sets its height to what it holds, and a browser
   that sizes fields to their content does so without it. */
.kvyk-prompt--multiline { align-items: flex-end; }
.kvyk-prompt--multiline .kvyk-prompt__icon { align-self: center; }
.kvyk-prompt--multiline .kvyk-prompt__input {
  height: auto;
  min-height: 40px;
  max-height: min(calc(8 * 22px + 18px), 33dvh);
  padding-block: 9px;
  overflow-y: auto;
  resize: none;
  field-sizing: content;
  font-size: 15px;
  line-height: 22px;
}
/* How many characters a message holds, shown quietly only near its limit;
   past it, in the error colour. */
.kvyk-prompt__count {
  margin: var(--kvyk-space-xs) 0 0;
  font-family: var(--kvyk-font-mono);
  font-size: 11px;
  line-height: 16px;
  text-align: right;
  color: var(--kvyk-on-surface-variant);
}
.kvyk-prompt__count--over { color: var(--kvyk-error); }

/* Messages written while the assistant works, waiting their turn at the foot
   of the conversation: the person's bubble, dashed and quieter, with what
   can be done with it under it. */
.kvyk-queued {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-md);
  margin: 0;
  padding: 0;
  list-style: none;
}
.kvyk-queued__item {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--kvyk-space-xs);
}
.kvyk-bubble--queued {
  max-width: 85%;
  white-space: pre-wrap;
  color: var(--kvyk-on-surface-variant);
  background: transparent;
  border-style: dashed;
}
.kvyk-queued__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--kvyk-space-xs);
}
.kvyk-queued__label {
  font-family: var(--kvyk-font-mono);
  font-size: 11px;
  line-height: 16px;
  color: var(--kvyk-on-surface-variant);
}

/* An assistant's answer, from its Markdown, in the size of the text around it:
   headings stay Inter at body sizes, tables are .kvyk-table, code is mono. */
.kvyk-prose > * { margin: 0; }
.kvyk-prose > * + * { margin-top: var(--kvyk-space-paragraph); }
.kvyk-prose strong { font-weight: var(--kvyk-weight-semibold); }
.kvyk-prose :is(h1, h2, h3, h4, h5, h6) {
  font-family: var(--kvyk-font-sans);
  font-weight: var(--kvyk-weight-semibold);
  color: var(--kvyk-on-surface);
  margin: 0;
}
.kvyk-prose :is(h1, h2) { font-size: 16px; line-height: var(--kvyk-leading-heading); }
.kvyk-prose :is(h3, h4, h5, h6) { font-size: inherit; line-height: var(--kvyk-leading-heading); }
.kvyk-prose > * + :is(h1, h2, h3, h4, h5, h6) { margin-top: var(--kvyk-space-lg); }
.kvyk-prose ul,
.kvyk-prose ol { padding-left: 1.25em; }
.kvyk-prose li > :is(ul, ol) { margin-top: var(--kvyk-space-2xs); }
.kvyk-prose li + li { margin-top: var(--kvyk-space-2xs); }
.kvyk-prose li > p { margin: 0; }
.kvyk-prose li > p + * { margin-top: var(--kvyk-space-2xs); }
.kvyk-prose hr {
  border: none;
  border-top: 1px solid var(--kvyk-outline-variant);
}
.kvyk-prose blockquote {
  margin: 0;
  padding-left: var(--kvyk-space-sm);
  border-left: 2px solid var(--kvyk-outline-variant);
  color: var(--kvyk-on-surface-variant);
}
.kvyk-prose pre {
  margin: 0;
  padding: var(--kvyk-space-sm);
  overflow-x: auto;
  border-radius: var(--kvyk-radius-sm);
  background: var(--kvyk-surface-container);
}
.kvyk-prose pre code { padding: 0; background: none; font-size: 12px; line-height: 18px; }
/* A table in an answer: the design system's, a little tighter. */
.kvyk-prose .kvyk-table thead th,
.kvyk-prose .kvyk-table tbody td { padding: var(--kvyk-space-xs) var(--kvyk-space-sm); }
.kvyk-prose .kvyk-table thead th { font-size: 11px; }
.kvyk-prose .kvyk-table tbody td { font-size: 13px; line-height: 18px; }
.kvyk-prose code {
  font-family: var(--kvyk-font-mono);
  font-size: 0.9em;
  padding: 0 4px;
  border-radius: var(--kvyk-radius-xs);
  background: var(--kvyk-surface-container);
}
.kvyk-prose a { color: var(--kvyk-link); text-decoration: underline; }

/* ---- Assistant ------------------------------------------------------------
   One conversation in three places (ADR-0042): the side panel in the
   sidebar's place on a desktop, resizable while open; the assistant page at
   full width; full screen on a phone, collapsible to a bar at the foot. */
.kvyk-sidebar--assistant {
  position: relative;
  width: var(--kvyk-assistant-width, 400px);
}
/* While the panel is open on a desktop it takes the nav's place. */
@media (min-width: 768px) {
  .kvyk-app-shell:has(> .kvyk-sidebar--assistant) > .kvyk-sidebar:not(.kvyk-sidebar--assistant) {
    display: none;
  }
}
.kvyk-assistant {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  background: var(--kvyk-surface-container-lowest);
}
.kvyk-assistant__header {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-xs);
  flex-shrink: 0;
  height: var(--kvyk-header-height);
  padding-inline: var(--kvyk-space-md) var(--kvyk-space-sm);
  border-bottom: 1px solid var(--kvyk-outline-variant);
}
.kvyk-assistant__title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kvyk-assistant__log {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--kvyk-space-lg) var(--kvyk-space-md);
}
/* Reply, over what the person selects in the conversation: it sits just
   above where the selection starts, centred on it, and scrolls with it. */
.kvyk-assistant__selection-reply {
  position: absolute;
  z-index: 2;
  /* translate, not transform: .kvyk-btn:active sets transform, and replacing
     this one moved the button from under the pointer, so the click was lost. */
  translate: -50% calc(-100% - var(--kvyk-space-2xs));
  box-shadow: var(--kvyk-elevation-2);
}
/* A selection at the top of the view leaves no room above it. */
.kvyk-assistant__selection-reply--below { translate: -50% var(--kvyk-space-2xs); }
/* Jump to latest: pinned to the foot of the conversation's view while the
   person reads further up and more comes in below. */
.kvyk-assistant__latest {
  position: sticky;
  bottom: 0;
  z-index: 2;
  display: flex;
  width: fit-content;
  margin: var(--kvyk-space-sm) auto 0;
  box-shadow: var(--kvyk-elevation-2);
}
/* The box to write in is the panel's last section, full width under a rule,
   not a box floating over the conversation; focus marks the rule. */
.kvyk-assistant__composer {
  flex-shrink: 0;
  padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
  border-top: 1px solid var(--kvyk-outline-variant);
  background: var(--kvyk-surface-container-lowest);
  transition: box-shadow var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-assistant__composer:focus-within { box-shadow: inset 0 2px 0 var(--kvyk-secondary); }
.kvyk-assistant__composer .kvyk-prompt,
.kvyk-assistant__composer .kvyk-prompt:focus-within {
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
}
/* The conversation's name in its header: the most important words there. */
.kvyk-assistant__heading {
  margin: 0;
  font-family: var(--kvyk-font-sans);
  font-size: 15px;
  line-height: 22px;
  font-weight: var(--kvyk-weight-semibold);
  color: var(--kvyk-on-surface);
}
/* An answer: plain text on the conversation, as wide as it, with no frame
   or sender, so the person's own messages are the only bubbles. It reads as
   an article: a size up from the controls around it, paragraphs and list
   items apart, a heading well clear of what came before and close to what
   it heads, a rule with room on both sides. */
.kvyk-assistant__reply {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-md);
  font-size: 15px;
  line-height: 1.7;
  color: var(--kvyk-on-surface);
}
.kvyk-assistant .kvyk-bubble { font-size: 15px; }
.kvyk-assistant__reply .kvyk-prose :is(h1, h2) { font-size: 17px; }
.kvyk-assistant__reply .kvyk-prose :is(h3, h4, h5, h6) { font-size: 15px; }
.kvyk-assistant__reply .kvyk-prose > * + :is(h1, h2, h3, h4, h5, h6) { margin-top: var(--kvyk-space-xl); }
.kvyk-assistant__reply .kvyk-prose > :is(h1, h2, h3, h4, h5, h6) + * { margin-top: var(--kvyk-space-sm); }
.kvyk-assistant__reply .kvyk-prose li + li { margin-top: var(--kvyk-space-sm); }
.kvyk-assistant__reply .kvyk-prose li li + li { margin-top: var(--kvyk-space-xs); }
.kvyk-assistant__reply .kvyk-prose li > :is(ul, ol) { margin-top: var(--kvyk-space-xs); }
.kvyk-assistant__reply .kvyk-prose > hr,
.kvyk-assistant__reply .kvyk-prose > hr + * { margin-top: var(--kvyk-space-xl); }
/* The header's toggle while what it shows is open. */
.kvyk-assistant__header .kvyk-btn[aria-pressed="true"] {
  background: var(--kvyk-surface-selected);
  color: var(--kvyk-on-surface);
}
/* A button that reads as a link, for a row that opens its details in place. */
.kvyk-link-button {
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: var(--kvyk-secondary);
  text-align: left;
  text-decoration: underline;
  cursor: pointer;
}
.kvyk-link-button:focus-visible { outline: none; box-shadow: var(--kvyk-ring); }
/* Code or JSON to read, such as a request body's schema. */
.kvyk-code-block {
  margin: 0;
  padding: var(--kvyk-space-md);
  overflow-x: auto;
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  line-height: 18px;
  border-radius: var(--kvyk-radius-sm);
  background: var(--kvyk-surface-container);
}

/* A help page's text, at the page's reading size rather than a chat's. */
.kvyk-help-page { max-width: 46rem; }
.kvyk-help-page .kvyk-prose { font-size: 16px; }
.kvyk-help-page .kvyk-prose :is(h1, h2) { font-size: 20px; }
.kvyk-help-list { grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr)); }
.kvyk-assistant__starter:is(a) { text-decoration: none; }

/* Notes the assistant keeps, one under the other, each with its actions. */
.kvyk-notes { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }
.kvyk-notes__item {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-xs);
  padding: var(--kvyk-space-sm) 0;
  border-bottom: 1px solid var(--kvyk-outline-variant);
}
.kvyk-notes__item:first-child { padding-top: 0; }
.kvyk-notes__item:last-child { border-bottom: none; }

/* First prompts on a new conversation, chosen for the person and the page:
   each a card that sends its prompt. */
/* Each starter a square card of its own, apart from the next. */
.kvyk-assistant__starters {
  display: grid;
  gap: var(--kvyk-space-sm);
  margin: var(--kvyk-space-sm) 0 0;
  padding: 0;
  list-style: none;
}
.kvyk-assistant__starter {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-2xs);
  width: 100%;
  padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
  text-align: left;
  font: inherit;
  color: var(--kvyk-on-surface);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  background: var(--kvyk-surface-container-lowest);
  cursor: pointer;
  transition: background-color var(--kvyk-duration) var(--kvyk-ease),
              border-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-assistant__starter:hover { background: var(--kvyk-surface-hover); border-color: var(--kvyk-outline); }
.kvyk-assistant__starter:focus-visible { outline: none; box-shadow: var(--kvyk-ring); }
.kvyk-assistant__starter-title {
  font-size: 14px;
  line-height: 20px;
  font-weight: var(--kvyk-weight-semibold);
}
.kvyk-assistant__starter-prompt {
  font-size: 12px;
  line-height: 16px;
  color: var(--kvyk-on-surface-variant);
}

/* Questions the assistant asks (ADR-0042): each in the input its kind needs,
   then Send and Skip. Its answers show after, as a short list. */
.kvyk-question {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-md);
  padding: var(--kvyk-space-md);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  background: var(--kvyk-surface-container-lowest);
}
.kvyk-question__item {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-sm);
  min-width: 0;
  margin: 0;
  padding: 0;
  border: none;
}
.kvyk-question__label {
  padding: 0;
  font-family: var(--kvyk-font-sans);
  font-size: 14px;
  line-height: 20px;
  font-weight: var(--kvyk-weight-semibold);
  color: var(--kvyk-on-surface);
}
/* A fieldset's legend is not one of its flex items, so the item's gap does
   not reach it: it keeps its own distance from the choices under it. */
legend.kvyk-question__label { margin-bottom: var(--kvyk-space-sm); }
.kvyk-question__choices {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--kvyk-space-sm);
}
.kvyk-question__choices > .kvyk-input,
.kvyk-question__choices > .kvyk-combobox { align-self: stretch; }
.kvyk-question__choices > .kvyk-choice + .kvyk-input { margin-top: var(--kvyk-space-xs); }
.kvyk-question__colour {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
}
.kvyk-question__colour input[type="color"] {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  padding: 2px;
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-sm);
  background: var(--kvyk-surface-container-lowest);
  cursor: pointer;
}
.kvyk-question__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kvyk-space-sm);
}
.kvyk-question__lines {
  margin: 0;
  padding-left: 1.25em;
  font-size: 14px;
  line-height: 20px;
}
.kvyk-question__answers {
  display: grid;
  gap: var(--kvyk-space-xs);
  margin: 0;
  padding-left: var(--kvyk-space-sm);
  border-left: 2px solid var(--kvyk-secondary);
}
.kvyk-question__answers dt { font-size: 12px; line-height: 16px; color: var(--kvyk-on-surface-variant); }
.kvyk-question__answers dd { margin: 0; font-size: 14px; line-height: 20px; }
/* A step the assistant took ("Read the model"), with how it went. */
.kvyk-assistant__step {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  color: var(--kvyk-on-surface-variant);
}
/* A turn's steps folded into one line: what it does now while it works, how
   many steps it took (and how many did not work) once done. The line is as
   quiet as a step's, with no frame or fill, and is the button that unfolds
   the list and folds it again. */
.kvyk-steps {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--kvyk-space-sm);
  min-width: 0;
}
.kvyk-steps__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  max-width: 100%;
  padding: 0;
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  line-height: 16px;
  text-align: left;
  color: var(--kvyk-on-surface-variant);
  background: none;
  border: none;
  border-radius: var(--kvyk-radius-xs);
  cursor: pointer;
}
.kvyk-steps__toggle:hover { color: var(--kvyk-on-surface); }
.kvyk-steps__toggle:focus-visible { outline: none; box-shadow: var(--kvyk-ring); }
.kvyk-steps__toggle .kvyk-icon { width: 14px; height: 14px; flex-shrink: 0; transition: transform var(--kvyk-duration-fast) var(--kvyk-ease); }
.kvyk-steps__toggle[aria-expanded="true"] .kvyk-icon { transform: rotate(180deg); }
.kvyk-steps__working { flex-shrink: 0; font-weight: var(--kvyk-weight-medium); color: var(--kvyk-on-surface); }
.kvyk-steps__now {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kvyk-steps__failed { flex-shrink: 0; color: var(--kvyk-on-error-container); }
/* A turn the person stopped: said beside its count, not as a failure. */
.kvyk-steps__stopped { flex-shrink: 0; color: var(--kvyk-on-surface); }
/* A step that failed and was then done again: said beside its line. */
.kvyk-steps__fixed { color: var(--kvyk-on-tertiary-fixed-variant); }
.kvyk-steps__list {
  display: grid;
  gap: var(--kvyk-space-sm);
  width: 100%;
  margin: 0;
  padding: 0 0 0 var(--kvyk-space-md);
  list-style: none;
  border-left: 2px solid var(--kvyk-outline-variant);
}
.kvyk-steps__list > li { display: grid; gap: var(--kvyk-space-xs); min-width: 0; }
/* The technical side of a step (the file read, the command run), kept off its main line. */
.kvyk-steps__detail {
  margin: 0 0 0 calc(8px + var(--kvyk-space-sm));
  font-family: var(--kvyk-font-mono);
  font-size: 11px;
  line-height: 16px;
  color: var(--kvyk-on-surface-variant);
  overflow-wrap: break-word;
}
/* The page's own version: one bar over the conversation, which fills the
   main column edge to edge at a reading width; the person's conversations
   open in a column beside it only when asked for. The page itself does not
   scroll: the list and the conversation do, and the box to write in stays at
   the foot of the window. On a phone the conversations show in its place. */
.kvyk-main:has(.kvyk-assistant-view) { overflow: hidden; }
.kvyk-page:has(> .kvyk-assistant-view) {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
  max-width: none;
  padding: 0;
}
.kvyk-assistant-view {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
}
.kvyk-assistant-page {
  display: grid;
  flex: 1;
  grid-template-columns: minmax(0, 1fr);
  min-height: 0;
  background: var(--kvyk-surface-container-lowest);
}
.kvyk-assistant-page.is-history { grid-template-columns: 280px minmax(0, 1fr); }
.kvyk-assistant-page__bar { padding-inline: var(--kvyk-space-sm) var(--kvyk-margin-desktop); }
.kvyk-assistant-page__bar .kvyk-assistant__heading { margin-left: var(--kvyk-space-xs); }
.kvyk-assistant-view .kvyk-assistant__log { padding-inline: var(--kvyk-margin-desktop); }
.kvyk-assistant-view .kvyk-chat,
.kvyk-assistant-view .kvyk-assistant__composer > .kvyk-prompt {
  max-width: 46rem;
  margin-inline: auto;
}
.kvyk-assistant-page__history {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--kvyk-outline-variant);
  background: var(--kvyk-surface-container-lowest);
}
.kvyk-assistant-page__back { display: none; }

/* A person's conversations: a search, then the newest first under Today,
   Yesterday and Earlier. A row's title leads; its time, and in a search the
   words that matched, follow smaller and muted. Its delete shows on hover or
   focus, and always on a touch screen. */
.kvyk-history {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
/* The search is the band itself, flush with the column: no box in a box. */
.kvyk-history__search {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  flex-shrink: 0;
  height: var(--kvyk-header-height);
  padding-inline: var(--kvyk-space-md) var(--kvyk-space-sm);
  border-bottom: 1px solid var(--kvyk-outline-variant);
  color: var(--kvyk-on-surface-variant);
  transition: background-color var(--kvyk-duration) var(--kvyk-ease),
              box-shadow var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-history__search:focus-within {
  background: var(--kvyk-surface-container-lowest);
  box-shadow: inset 0 -2px 0 var(--kvyk-secondary);
}
.kvyk-history__input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: none;
  background: none;
  font-family: var(--kvyk-font-sans);
  font-size: 14px;
  line-height: 20px;
  color: var(--kvyk-on-surface);
}
.kvyk-history__input::placeholder { color: var(--kvyk-on-surface-variant); }
.kvyk-history__input:focus,
.kvyk-history__input:focus-visible { outline: none; box-shadow: none; }
.kvyk-history__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding-block: var(--kvyk-space-sm) var(--kvyk-space-md);
}
.kvyk-history__group + .kvyk-history__group { margin-top: var(--kvyk-space-md); }
.kvyk-history__heading {
  margin: 0;
  padding: var(--kvyk-space-xs) var(--kvyk-space-md);
  font-size: 11px;
}
.kvyk-history__item .kvyk-history__delete { margin-right: var(--kvyk-space-2xs); }
.kvyk-history__list { margin: 0; padding: 0; list-style: none; }
.kvyk-history__item {
  display: flex;
  align-items: center;
  margin-inline: var(--kvyk-space-sm);
  border-radius: var(--kvyk-radius-sm);
  transition: background-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-history__item:hover { background: var(--kvyk-surface-hover); }
.kvyk-history__item.is-active { background: var(--kvyk-surface-selected); }
.kvyk-history__open {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--kvyk-space-2xs);
  min-width: 0;
  padding: var(--kvyk-space-sm);
  border: none;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.kvyk-history__open:focus-visible { outline: none; box-shadow: inset var(--kvyk-ring); border-radius: var(--kvyk-radius-sm); }
.kvyk-history__line {
  display: flex;
  align-items: baseline;
  gap: var(--kvyk-space-sm);
  min-width: 0;
}
.kvyk-history__title {
  flex: 1;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  font-family: var(--kvyk-font-sans);
  font-size: 14px;
  line-height: 20px;
  font-weight: var(--kvyk-weight-regular);
  color: var(--kvyk-on-surface);
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* An answer the person has not read yet. */
.kvyk-history__item.is-unread .kvyk-history__title { font-weight: var(--kvyk-weight-semibold); }
.kvyk-history__excerpt {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  font-size: 13px;
  line-height: 18px;
  color: var(--kvyk-on-surface);
}
.kvyk-history__meta {
  margin: 0;
  font-family: var(--kvyk-font-sans);
  font-size: 12px;
  line-height: 16px;
  color: var(--kvyk-on-surface-variant);
}
/* A row's time and Delete are there only while it is pointed at, focused or
   (on a touch screen) open; then its name gives way to them, cut short. */
.kvyk-history__line .kvyk-history__meta { flex-shrink: 0; }
.kvyk-history__delete { flex-shrink: 0; }
/* Where the next page loads as the list is scrolled to its end. */
.kvyk-history__more { min-height: 1px; }
.kvyk-history__note {
  margin: 0;
  padding: var(--kvyk-space-sm) var(--kvyk-space-md);
  font-size: 14px;
  line-height: 20px;
  color: var(--kvyk-on-surface-variant);
}

/* A handle on a panel's edge that drags (or, focused, arrows) its width. */
.kvyk-resizer {
  position: absolute;
  top: 0;
  right: -4px;
  bottom: 0;
  width: 8px;
  cursor: col-resize;
  z-index: 1;
  background: transparent;
  touch-action: none;
}
.kvyk-resizer::after {
  content: "";
  position: absolute;
  inset: 0 3px;
  background: transparent;
  transition: background var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-resizer:hover::after,
.kvyk-resizer:focus-visible::after,
.kvyk-resizer.is-dragging::after { background: var(--kvyk-secondary); }
.kvyk-resizer:focus-visible { outline: none; box-shadow: none; }

/* What shows only in one size: the phone's collapse, the desktop's expand. */
.kvyk-assistant__collapse,
.kvyk-assistant__bar { display: none; }
@media (max-width: 767px) {
  .kvyk-sidebar--assistant {
    display: flex;
    position: fixed;
    inset: 0;
    width: 100%;
    z-index: var(--kvyk-z-overlay);
  }
  .kvyk-sidebar--assistant .kvyk-resizer,
  .kvyk-assistant__expand { display: none; }
  .kvyk-assistant__collapse { display: inline-flex; }
  /* Collapsed: a bar at the foot of the page, tapped to expand. */
  .kvyk-sidebar--assistant.is-collapsed {
    inset: auto 0 0 0;
    height: auto;
    border-right: none;
    border-top: 1px solid var(--kvyk-outline-variant);
    box-shadow: var(--kvyk-elevation-3);
  }
  .kvyk-sidebar--assistant.is-collapsed .kvyk-assistant { display: none; }
  .kvyk-sidebar--assistant.is-collapsed .kvyk-assistant__bar {
    display: flex;
    align-items: center;
    gap: var(--kvyk-space-sm);
    width: 100%;
    min-height: 56px;
    padding: var(--kvyk-space-sm) var(--kvyk-space-md);
    border: none;
    background: var(--kvyk-surface-container-lowest);
    color: var(--kvyk-on-surface);
    text-align: left;
    font: inherit;
    cursor: pointer;
  }
  /* The page on a phone: the bar's actions as icons, and the conversations
     in the conversation's place while they are open. */
  .kvyk-assistant-page__bar { padding-inline: var(--kvyk-space-xs) var(--kvyk-space-sm); }
  .kvyk-assistant-page__new { padding-inline: var(--kvyk-space-sm); }
  .kvyk-assistant-page__new-label { display: none; }
  .kvyk-assistant-view .kvyk-assistant__log { padding-inline: var(--kvyk-space-md); }
  .kvyk-assistant-page.is-history { grid-template-columns: minmax(0, 1fr); }
  .kvyk-assistant-page__history { border-right: none; }
  .kvyk-assistant-page.is-history .kvyk-assistant { display: none; }
  .kvyk-assistant-page__back {
    display: inline-flex;
    align-self: flex-start;
    margin: var(--kvyk-space-sm) var(--kvyk-space-sm) 0;
  }
}

/* ---- Ask kvyk --------------------------------------------------------------
   The prompt on every page, on a bar of its own under the app bar, the main
   column's full width: a quiet field with its shortcut, which opens the
   assistant in the side panel. The two bars stick to the top together
   (`.kvyk-appbar-group` around them). On a phone the shortcut is left out. */
.kvyk-appbar-group {
  position: sticky;
  top: 0;
  flex-shrink: 0;
  z-index: var(--kvyk-z-header);
}
.kvyk-askbar {
  display: flex;
  box-sizing: border-box;
  height: var(--kvyk-askbar-height);
  padding: var(--kvyk-space-sm) var(--kvyk-margin-desktop);
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--kvyk-outline-variant);
}
.kvyk-ask {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  flex: 1;
  min-width: 0;
  height: 36px;
  padding-inline: var(--kvyk-space-sm-md) var(--kvyk-space-xs);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-sm);
  background: var(--kvyk-surface-container-lowest);
  color: var(--kvyk-secondary);
  transition: border-color var(--kvyk-duration) var(--kvyk-ease),
              box-shadow var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-ask:hover { border-color: var(--kvyk-outline); }
.kvyk-ask:focus-within {
  border-color: var(--kvyk-secondary);
  box-shadow: 0 0 0 3px var(--kvyk-ring-color);
}
.kvyk-ask__input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: none;
  background: none;
  font-family: var(--kvyk-font-sans);
  font-size: 14px;
  color: var(--kvyk-on-surface);
}
.kvyk-ask__input::placeholder { color: var(--kvyk-on-surface-variant); }
.kvyk-ask__input:focus,
.kvyk-ask__input:focus-visible { outline: none; box-shadow: none; }
.kvyk-ask:focus-within .kvyk-ask__keys { visibility: hidden; }
@media (max-width: 767px) {
  .kvyk-askbar { padding-inline: var(--kvyk-margin-mobile); }
  .kvyk-askbar:not(.is-open) { display: none; }
  .kvyk-main:not(:has(.kvyk-askbar.is-open)) .kvyk-page-header--sticky { top: var(--kvyk-header-height); }
  .kvyk-ask .kvyk-ask__keys { display: none; }
}

/* The app bar's controls on a phone, smaller: Ask kvyk behind a sparkle
   button (`.kvyk-appbar__ask`) that shows its bar (`.kvyk-askbar.is-open`),
   the stage as a drop-down (`.kvyk-appbar__stage-menu`) in place of its
   segmented switch (`.kvyk-appbar__stage`), and a menu button's arrow left out
   where the button alone says enough (`.kvyk-appbar__chevron`: the language's
   flag). On a desktop only the segmented switch and the arrows show. */
.kvyk-appbar__chevron { display: inline-flex; }
.kvyk-appbar .kvyk-appbar__ask,
.kvyk-appbar .kvyk-appbar__stage-menu { display: none; }
@media (max-width: 767px) {
  .kvyk-appbar .kvyk-appbar__ask { display: inline-flex; color: var(--kvyk-secondary); }
  .kvyk-appbar .kvyk-appbar__stage-menu { display: block; }
  .kvyk-appbar .kvyk-appbar__stage,
  .kvyk-appbar .kvyk-appbar__chevron { display: none; }
}

/* ---- Home -----------------------------------------------------------------
   An organisation's front door: what the person wants to do, asked in a
   large box with the first prompts under it, then the organisation in a few
   counts that link on. */
.kvyk-home {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-2xl);
}
.kvyk-home__ask {
  display: flex;
  flex-direction: column;
  gap: var(--kvyk-space-md);
  width: 100%;
  max-width: 44rem;
  margin: var(--kvyk-space-xl) auto 0;
}
.kvyk-home__ask > .kvyk-overline { margin: 0; text-align: center; }
.kvyk-home__ask > h1 { margin: 0; text-align: center; }
.kvyk-home__prompt { padding: var(--kvyk-space-sm) var(--kvyk-space-sm) var(--kvyk-space-sm) var(--kvyk-space-xs); }
.kvyk-home__prompt .kvyk-prompt__input { height: 48px; }
.kvyk-home__ask .kvyk-assistant__starters {
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  margin: 0;
}
.kvyk-home__tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: var(--kvyk-space-md);
  margin: 0;
  padding: 0;
  list-style: none;
}
.kvyk-home__tiles > li { display: flex; }
.kvyk-home__tile {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--kvyk-space-xs);
  padding: var(--kvyk-space-md) var(--kvyk-space-lg);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  background: var(--kvyk-surface-container-lowest);
  color: var(--kvyk-on-surface);
  text-decoration: none;
  transition: border-color var(--kvyk-duration) var(--kvyk-ease),
              background-color var(--kvyk-duration) var(--kvyk-ease);
}
.kvyk-home__tile:hover {
  border-color: var(--kvyk-outline);
  background: var(--kvyk-surface-hover);
  text-decoration: none;
}
.kvyk-home__tile:focus-visible { outline: none; box-shadow: var(--kvyk-ring); }
.kvyk-home__tile-head {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  color: var(--kvyk-on-surface-variant);
}
.kvyk-home__apps {
  margin: 0;
  padding: 0;
  list-style: none;
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  background: var(--kvyk-surface-container-lowest);
}
.kvyk-home__apps > li + li { border-top: 1px solid var(--kvyk-outline-variant); }
.kvyk-home__app {
  display: flex;
  align-items: center;
  gap: var(--kvyk-space-sm);
  padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
  color: var(--kvyk-on-surface);
  text-decoration: none;
}
.kvyk-home__app:hover { background: var(--kvyk-surface-hover); text-decoration: none; }
.kvyk-home__app > .kvyk-icon { color: var(--kvyk-on-surface-variant); }
@media (max-width: 767px) {
  .kvyk-home { gap: var(--kvyk-space-xl); }
  .kvyk-home__ask { margin-top: 0; }
}

/* ---- Alert / Insight ----------------------------------------------------- */
.kvyk-alert {
  --_accent: var(--kvyk-secondary);
  --_bg: var(--kvyk-surface-container-low);
  display: flex;
  gap: var(--kvyk-space-sm);
  padding: var(--kvyk-space-md);
  background: var(--_bg);
  border: 1px solid var(--kvyk-outline-variant);
  border-left: 3px solid var(--_accent);
  border-radius: var(--kvyk-radius-md);
}
.kvyk-alert__icon { color: var(--_accent); flex-shrink: 0; }
.kvyk-alert__title { font-weight: var(--kvyk-weight-semibold); color: var(--kvyk-on-surface); font-size: 14px; }
.kvyk-alert__body { font-size: 14px; line-height: var(--kvyk-leading-body); color: var(--kvyk-on-surface-variant); }
.kvyk-alert--info { --_accent: var(--kvyk-secondary); }
.kvyk-alert--success { --_accent: var(--kvyk-tertiary-fixed-dim); }
.kvyk-alert--warning { --_accent: #b8860b; }
.kvyk-alert--danger { --_accent: var(--kvyk-error); --_bg: var(--kvyk-error-container); }
/* AI suggestion variant: subtle blue glow, no hard left bar. */
.kvyk-alert--ai {
  border: 1px solid var(--kvyk-secondary-fixed-dim);
  border-left: 1px solid var(--kvyk-secondary-fixed-dim);
  background: var(--kvyk-surface-container-low);
}

/* ---- Info card ----------------------------------------------------------- */
/* What a page is about, said once, quietly: an info icon, a sentence or two
   and a link to the documentation. No rail, no title, so it reads as a note
   and never as a warning. */
.kvyk-info {
  display: flex;
  align-items: flex-start;
  gap: var(--kvyk-space-sm-md);
  padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
  background: var(--kvyk-surface-container-low);
  border: 1px solid var(--kvyk-surface-container-high);
  border-radius: var(--kvyk-radius-md);
}
.kvyk-info__icon {
  display: inline-flex;
  padding-top: 2px;
  color: var(--kvyk-secondary);
  flex-shrink: 0;
}
.kvyk-info__body {
  max-width: var(--kvyk-measure);
  font-size: 14px;
  line-height: var(--kvyk-leading-body);
  color: var(--kvyk-on-surface-variant);
}
.kvyk-info__link {
  display: inline-flex;
  align-items: center;
  gap: var(--kvyk-space-xs);
  margin-left: var(--kvyk-space-xs);
  font-weight: var(--kvyk-weight-medium);
  white-space: nowrap;
}
.kvyk-info__link .kvyk-icon { width: 14px; height: 14px; }

/* ---- Toast --------------------------------------------------------------- */
/* What just happened to something the person did: a short message that floats
   over the page and goes, bottom right on a desktop, across the foot of the
   screen on a phone. The region holds the newest last. */
.kvyk-toasts {
  position: fixed;
  right: var(--kvyk-space-lg);
  bottom: var(--kvyk-space-lg);
  z-index: var(--kvyk-z-toast);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--kvyk-space-sm);
  width: min(420px, calc(100vw - 2 * var(--kvyk-space-md)));
  margin: 0;
  padding: 0;
  list-style: none;
  pointer-events: none;
}
.kvyk-toast {
  --_accent: var(--kvyk-on-tertiary-container);
  display: flex;
  align-items: flex-start;
  gap: var(--kvyk-space-sm);
  width: 100%;
  padding: var(--kvyk-space-xs) var(--kvyk-space-xs) var(--kvyk-space-xs) var(--kvyk-space-md);
  color: var(--kvyk-on-surface);
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-left: 3px solid var(--_accent);
  border-radius: var(--kvyk-radius-md);
  box-shadow: var(--kvyk-elevation-3);
  pointer-events: auto;
  animation: kvyk-toast-in var(--kvyk-duration-slow) var(--kvyk-ease);
}
.kvyk-toast.is-leaving { animation: kvyk-toast-out var(--kvyk-duration) var(--kvyk-ease) forwards; }
.kvyk-toast--success { --_accent: var(--kvyk-on-tertiary-container); }
.kvyk-toast--danger { --_accent: var(--kvyk-error); }
.kvyk-toast__icon {
  display: inline-flex;
  padding-block: 10px;
  color: var(--_accent);
  flex-shrink: 0;
}
.kvyk-toast__text {
  flex: 1;
  min-width: 0;
  padding-block: 8px;
  font-size: 14px;
  line-height: var(--kvyk-leading-body);
  overflow-wrap: break-word;
}
.kvyk-toast__close { flex-shrink: 0; }
@media (max-width: 767px) {
  .kvyk-toasts {
    left: var(--kvyk-space-md);
    right: var(--kvyk-space-md);
    bottom: var(--kvyk-space-md);
    width: auto;
    align-items: stretch;
  }
}
@keyframes kvyk-toast-in {
  from { opacity: 0; transform: translateY(8px); }
}
@keyframes kvyk-toast-out {
  to { opacity: 0; transform: translateY(8px); }
}

/* ---- Dialog -------------------------------------------------------------- */
/* A question that must be answered before going on, such as "Delete this?":
   the native <dialog>, opened with showModal(), so the page behind is out of
   reach and Escape cancels. Its content sits in __panel, so a click on the
   backdrop is a click on the dialog itself. The confirm button is a
   .kvyk-btn--danger when the step cannot be undone. It sits wherever its
   trigger does, a table's actions cell among them, so it sets its own text
   alignment and wrapping rather than inheriting that cell's. */
.kvyk-dialog {
  width: min(480px, calc(100vw - 2 * var(--kvyk-space-md)));
  text-align: start;
  white-space: normal;
  overflow-wrap: break-word;
  max-width: none;
  max-height: calc(100dvh - 2 * var(--kvyk-space-md));
  margin: auto;
  padding: 0;
  overflow: auto;
  color: var(--kvyk-on-surface);
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-lg);
  box-shadow: var(--kvyk-elevation-3);
}
.kvyk-dialog[open] { animation: kvyk-dialog-in var(--kvyk-duration) var(--kvyk-ease); }
.kvyk-dialog::backdrop { background: var(--kvyk-scrim); }
.kvyk-dialog__panel {
  --_flow-gap: var(--kvyk-space-sm-md);
  display: flex;
  flex-direction: column;
  gap: var(--_flow-gap);
  padding: var(--kvyk-space-lg);
}
.kvyk-dialog__title {
  font-size: 18px;
  line-height: var(--kvyk-leading-heading);
  font-weight: var(--kvyk-weight-semibold);
  color: var(--kvyk-on-surface);
}
/* A dialog over nearly the whole window, for work that needs the room, such
   as a template's text beside its preview: a __bar with its title, its
   controls and its close button, over content that fills the rest
   (.kvyk-template-layout--fill), each part scrolling on its own. */
.kvyk-dialog.kvyk-dialog--full {
  width: min(1200px, calc(100vw - 2 * var(--kvyk-space-lg)));
  height: calc(100dvh - 2 * var(--kvyk-space-lg));
  max-height: none;
  overflow: hidden;
}
.kvyk-dialog--full > .kvyk-dialog__panel { height: 100%; min-height: 0; box-sizing: border-box; }
@media (max-width: 479px) {
  .kvyk-dialog.kvyk-dialog--full { width: calc(100vw - 2 * var(--kvyk-space-md)); height: calc(100dvh - 2 * var(--kvyk-space-md)); }
  .kvyk-dialog--full > .kvyk-dialog__panel { padding: var(--kvyk-space-md); }
}
.kvyk-dialog__bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--kvyk-space-sm) var(--kvyk-space-md); }
.kvyk-dialog__bar > .kvyk-dialog__title { flex: 1 1 auto; min-width: 0; margin: 0; }
/* The part of a full dialog that takes the room left and scrolls, such as a grid of tiles to pick from. */
.kvyk-dialog__fill { flex: 1 1 auto; min-height: 0; overflow: auto; }
.kvyk-template-layout.kvyk-template-layout--fill { flex: 1 1 auto; min-height: 0; grid-template-rows: minmax(0, 1fr); align-items: stretch; }
.kvyk-template-layout--fill > * { min-height: 0; overflow: auto; }
.kvyk-template-layout--fill .kvyk-template-preview { position: static; }
@media (max-width: 1023px) {
  .kvyk-template-layout.kvyk-template-layout--fill:not(.kvyk-template-layout--single) { grid-template-rows: minmax(0, 1fr) minmax(0, 1fr); }
}
.kvyk-dialog__body {
  font-size: 14px;
  line-height: var(--kvyk-leading-body);
  color: var(--kvyk-on-surface-variant);
}
.kvyk-dialog__footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--kvyk-space-sm);
  margin-top: var(--kvyk-space-sm);
}
/* A footer with something at its start too, such as the paging of what the dialog lists. */
.kvyk-dialog__footer--split { justify-content: space-between; align-items: center; }
@media (max-width: 479px) {
  .kvyk-dialog__footer { flex-direction: column-reverse; }
  .kvyk-dialog__footer > .kvyk-btn { width: 100%; }
}
@keyframes kvyk-dialog-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
}

/* ---- List (activity / settings rows) ------------------------------------ */
.kvyk-list {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  overflow: hidden;
}
.kvyk-list-item {
  display: flex;
  gap: var(--kvyk-space-md);
  padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
  transition: background-color var(--kvyk-duration) var(--kvyk-ease);
}
/* A row with small buttons is as tall as a row of text, not taller. */
.kvyk-list-item:has(.kvyk-btn--sm) { padding-block: var(--kvyk-space-xs); align-items: center; }
.kvyk-list-item + .kvyk-list-item { border-top: 1px solid var(--kvyk-outline-variant); }
.kvyk-list-item--interactive { cursor: pointer; }
.kvyk-list-item--interactive:hover { background: var(--kvyk-surface-hover); }
/* A list whose order matters: each row leads with its number. */
.kvyk-list--numbered { counter-reset: kvyk-list; }
.kvyk-list--numbered > .kvyk-list-item { counter-increment: kvyk-list; }
.kvyk-list--numbered > .kvyk-list-item::before {
  content: counter(kvyk-list);
  min-width: 2ch;
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  color: var(--kvyk-on-surface-variant);
  text-align: right;
}
.kvyk-list-item__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--kvyk-radius-circle);
  flex-shrink: 0;
  background: var(--kvyk-surface-container);
  color: var(--kvyk-secondary);
}

/* ---- Table --------------------------------------------------------------- */
.kvyk-table-wrap {
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  /* Scroll a too-wide table horizontally instead of clipping it; the rounded
     corners are still clipped, and the scrollbar only shows when it overflows. */
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--kvyk-outline) transparent;
}
/* A table wider than its wrap scrolls sideways, and says so: a shade on the
   edge that hides columns, gone once scrolled to it (the covers scroll with
   the table, the shades stay with the wrap), and a scrollbar that shows. */
.kvyk-table-wrap {
  background:
    linear-gradient(to right, var(--kvyk-surface-container-lowest) 30%, transparent) left / 24px 100% no-repeat local,
    linear-gradient(to left, var(--kvyk-surface-container-lowest) 30%, transparent) right / 24px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, var(--kvyk-scroll-shadow), transparent) left / 12px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, var(--kvyk-scroll-shadow), transparent) right / 12px 100% no-repeat scroll,
    var(--kvyk-surface-container-lowest);
}
.kvyk-table-wrap::-webkit-scrollbar { height: 8px; }
.kvyk-table-wrap::-webkit-scrollbar-thumb {
  background: var(--kvyk-outline);
  border-radius: var(--kvyk-radius-pill);
}
.kvyk-table-wrap::-webkit-scrollbar-track { background: transparent; }
/* A table with a footer band under its last row (counts, paging): the panel
   carries the border, the wrap inside scrolls, and the band does not. */
.kvyk-table-panel {
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-card);
  background: var(--kvyk-surface-container-lowest);
  overflow: hidden;
}
.kvyk-table-panel > :is(.kvyk-table-wrap, .kvyk-list) { border: none; border-radius: 0; }
.kvyk-table-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--kvyk-space-sm) var(--kvyk-space-md);
  padding: var(--kvyk-space-sm) var(--kvyk-space-md);
  border-top: 1px solid var(--kvyk-outline-variant);
  color: var(--kvyk-on-surface-variant);
}
.kvyk-table { width: 100%; border-collapse: collapse; }
.kvyk-table thead th {
  text-align: left;
  padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
  font-family: var(--kvyk-font-mono);
  font-size: 11px;
  line-height: 16px;
  font-weight: var(--kvyk-weight-medium);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--kvyk-on-surface-variant);
  border-bottom: 1px solid var(--kvyk-outline-variant);
  white-space: nowrap;
}
.kvyk-table tbody td {
  padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
  vertical-align: middle;
  font-size: 14px;
  line-height: 20px;
  color: var(--kvyk-on-surface);
  border-bottom: 1px solid var(--kvyk-outline-variant);
}
.kvyk-table tbody tr:last-child td { border-bottom: none; }
/* Running text in a cell sets at the cell's own line (20px at 14px), so a
   paragraph there keeps the row as tall as a row of text. */
.kvyk-table :is(th, td) { --kvyk-leading-body: calc(20 / 14); }
/* A row's quieter second line, under its main value. */
.kvyk-table__secondary {
  margin-top: var(--kvyk-space-xs);
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  line-height: 16px;
  color: var(--kvyk-on-surface-variant);
}
/* Numbers line up on their last digit. */
.kvyk-table .is-numeric {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
/* A sortable column's header is a button; `aria-sort` on the cell says which way. */
.kvyk-table thead th button {
  display: inline-flex;
  align-items: center;
  gap: var(--kvyk-space-xs);
  padding: 0;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}
.kvyk-table thead th button:hover,
.kvyk-table thead th[aria-sort] button { color: var(--kvyk-on-surface); }
.kvyk-table thead th button .kvyk-icon { width: 14px; height: 14px; }
.kvyk-table tbody tr { transition: background-color var(--kvyk-duration) var(--kvyk-ease); }
/* Rows alternate, so the eye keeps its line across a wide table. A row's
   detail opened under it (.kvyk-table__detail) belongs to it: it takes that
   row's colour and does not count, so the rows after it keep alternating. */
.kvyk-table tbody tr:where(:nth-child(even of :not(.kvyk-table__detail))),
.kvyk-table tbody tr:where(:nth-child(even of :not(.kvyk-table__detail))) + tr.kvyk-table__detail {
  background: var(--kvyk-table-stripe);
}
.kvyk-table tbody tr:not(.kvyk-table__detail):hover { background: var(--kvyk-table-hover); }
.kvyk-table tbody tr:has(.kvyk-btn--sm) td { padding-block: var(--kvyk-space-xs); }
/* A grid of records: each short value on one line; a long text gives way
   instead, at most two lines and then an ellipsis (the record's page shows it
   whole), so the columns fit before the table has to scroll. */
.kvyk-table--grid tbody td { white-space: nowrap; }
.kvyk-table--grid tbody td.is-long {
  min-width: 10rem;
  max-width: 24rem;
  white-space: normal;
}
.kvyk-clamp {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow-wrap: break-word;
}
/* One line and then an ellipsis, the whole text in the element's title. In a
   table cell it takes the room the other columns leave, never less than a
   readable width, so the table scrolls before the text disappears. */
.kvyk-truncate {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kvyk-table td:has(> .kvyk-truncate) { width: 100%; max-width: 0; min-width: 12rem; }
/* The cell of a row's actions: at the row's end, its buttons close together. */
.kvyk-table td.kvyk-table__actions { text-align: right; white-space: nowrap; }
.kvyk-table td.kvyk-table__actions > * + * { margin-left: var(--kvyk-space-xs); }
.kvyk-table td.kvyk-table__actions .kvyk-cluster { justify-content: flex-end; flex-wrap: nowrap; }
/* A last cell of only buttons is a row's actions too, without the class. */
.kvyk-table tbody td:last-child:has(> .kvyk-btn, > .kvyk-cluster > .kvyk-btn) { text-align: right; white-space: nowrap; }
.kvyk-table tbody td:last-child > .kvyk-cluster:has(> .kvyk-btn) { justify-content: flex-end; flex-wrap: nowrap; }
/* A table that becomes a card per row on a phone (#549), so it never runs
   wider than the screen however many columns it has: a row's cells side by
   side and wrapping, each under its column's name from its data-label (the
   header row is then read out only). A long text, a row's actions and a
   detail row take the card's whole width. */
@media (max-width: 767px) {
  .kvyk-table--stack,
  .kvyk-table--stack tbody { display: block; }
  .kvyk-table--stack thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
  .kvyk-table--stack tbody tr {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(5rem, 1fr));
    gap: var(--kvyk-space-sm) var(--kvyk-space-md);
    padding: var(--kvyk-space-sm-md) var(--kvyk-space-md);
    border-bottom: 1px solid var(--kvyk-outline-variant);
  }
  .kvyk-table--stack tbody tr:last-child { border-bottom: none; }
  .kvyk-table--stack tbody td,
  .kvyk-table--stack tbody tr td:is(.is-long, :has(> .kvyk-truncate)),
  .kvyk-table--stack tbody tr:has(.kvyk-btn--sm) td {
    display: block;
    width: auto;
    min-width: 0;
    max-width: none;
    padding: 0;
    border-bottom: none;
  }
  .kvyk-table--stack tbody td,
  .kvyk-table--stack tbody tr td:is(.is-numeric, .is-long) {
    text-align: left;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .kvyk-table--stack tbody td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 2px;
    font-family: var(--kvyk-font-mono);
    font-size: 11px;
    line-height: 16px;
    font-weight: var(--kvyk-weight-medium);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--kvyk-on-surface-variant);
  }
  .kvyk-table--stack tbody td:is(.is-long, .kvyk-table__actions, [colspan], :has(> .kvyk-truncate)),
  .kvyk-table--stack tbody td:last-child:has(> .kvyk-btn, > .kvyk-cluster > .kvyk-btn) { grid-column: 1 / -1; }
}

/* ---- Tooltip ------------------------------------------------------------- */
.kvyk-tooltip { position: relative; display: inline-flex; }
.kvyk-tooltip__bubble {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: 6px 10px;
  background: var(--kvyk-inverse-surface);
  color: var(--kvyk-inverse-on-surface);
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  line-height: 16px;
  white-space: nowrap;
  border-radius: var(--kvyk-radius-sm);
  box-shadow: var(--kvyk-elevation-2);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--kvyk-duration) var(--kvyk-ease),
              transform var(--kvyk-duration) var(--kvyk-ease);
  z-index: var(--kvyk-z-tooltip);
  /* Its own type, whatever its trigger sits in: a table header's capitals
     and spacing are not the tip's. */
  text-align: start;
  text-transform: none;
  letter-spacing: normal;
  font-weight: var(--kvyk-weight-regular);
}
.kvyk-tooltip:hover .kvyk-tooltip__bubble,
.kvyk-tooltip:focus-within .kvyk-tooltip__bubble {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
/* A tip of a sentence or two wraps instead of running off a narrow panel. */
.kvyk-tooltip__bubble--wrap {
  width: max-content;
  max-width: 240px;
  white-space: normal;
}
/* A tip that opens from its trigger's start edge, for a trigger near the
   left of a narrow panel, where a centred bubble would be cut off. */
.kvyk-tooltip--start .kvyk-tooltip__bubble { left: 0; transform: translateY(4px); }
.kvyk-tooltip--start:hover .kvyk-tooltip__bubble,
.kvyk-tooltip--start:focus-within .kvyk-tooltip__bubble { transform: translateY(0); }
/* A tip that opens from its trigger's end edge, for a trigger near the right. */
.kvyk-tooltip--end .kvyk-tooltip__bubble { left: auto; right: 0; transform: translateY(4px); }
.kvyk-tooltip--end:hover .kvyk-tooltip__bubble,
.kvyk-tooltip--end:focus-within .kvyk-tooltip__bubble { transform: translateY(0); }

/* A tip that opens below its trigger, for a trigger along the top of a
   scrolling box, a table's header, where a tip above would be cut off. */
.kvyk-tooltip--below .kvyk-tooltip__bubble { top: calc(100% + 8px); bottom: auto; }
/* No tip over the panel its trigger has open. */
.kvyk-tooltip:has([aria-expanded="true"]) .kvyk-tooltip__bubble { opacity: 0; }

/* ---- Keyboard key -------------------------------------------------------- */
.kvyk-kbd {
  display: inline-block;
  padding: 2px 6px;
  font-family: var(--kvyk-font-mono);
  font-size: 12px;
  line-height: 16px;
  color: var(--kvyk-on-surface-variant);
  background: var(--kvyk-surface-container);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-xs);
}


/* A panel opened by a button beside it, over the page: a list's filter, sort
   or columns. It opens below the button, from its start (or, with --end, from
   its far edge), and never runs wider than the screen. */
.kvyk-popover-anchor {
  position: relative;
  display: inline-flex;
}
.kvyk-popover {
  position: absolute;
  top: calc(100% + var(--kvyk-space-xs));
  left: 0;
  z-index: var(--kvyk-z-overlay);
  width: max-content;
  min-width: 16rem;
  max-width: min(40rem, calc(100vw - 2 * var(--kvyk-space-md)));
  max-height: min(32rem, 70vh);
  overflow: auto;
  padding: var(--kvyk-space-md);
  background: var(--kvyk-surface-container-lowest);
  border: 1px solid var(--kvyk-outline-variant);
  border-radius: var(--kvyk-radius-sm);
  box-shadow: var(--kvyk-elevation-2);
}
.kvyk-popover--end {
  left: auto;
  right: 0;
}
/* Opens upwards, for a button at the foot of the screen, as the assistant's box is. */
.kvyk-popover--up {
  top: auto;
  bottom: calc(100% + var(--kvyk-space-xs));
}
/* A menu in a popover: each choice a ghost button the width of the panel, its icon before it. */
.kvyk-popover--menu { min-width: 12rem; padding: var(--kvyk-space-xs); }
.kvyk-popover__item { justify-content: flex-start; width: 100%; }
/* On a phone it rises from the bottom of the screen instead, full width. */
@media (max-width: 767px) {
  .kvyk-popover {
    position: fixed;
    top: auto;
    left: var(--kvyk-space-md);
    right: var(--kvyk-space-md);
    bottom: var(--kvyk-space-md);
    width: auto;
    min-width: 0;
    max-width: none;
  }
}

/* ==========================================================================
   7. UTILITIES
   --------------------------------------------------------------------------
   A deliberately small set. Reach for tokens + components first; these cover
   the recurring one-offs without becoming a utility framework.
   ========================================================================== */
.kvyk-text-muted { color: var(--kvyk-on-surface-variant); }
.kvyk-text-accent { color: var(--kvyk-secondary); }
.kvyk-text-success { color: var(--kvyk-on-tertiary-container); }
.kvyk-text-danger { color: var(--kvyk-error); }
.kvyk-text-balance { text-wrap: balance; }
.kvyk-text-center { text-align: center; }

.kvyk-flex-1 { flex: 1; }
.kvyk-grow { flex-grow: 1; }
.kvyk-items-center { align-items: center; }
.kvyk-items-start { align-items: flex-start; }
.kvyk-items-end { align-items: flex-end; }
.kvyk-nowrap { white-space: nowrap; }
.kvyk-measure { max-width: var(--kvyk-measure); }
.kvyk-list-reset { margin: 0; padding: 0; list-style: none; }
.kvyk-justify-between { justify-content: space-between; }

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

.kvyk-elevation-1 { box-shadow: var(--kvyk-elevation-1); }
.kvyk-elevation-2 { box-shadow: var(--kvyk-elevation-2); }
.kvyk-elevation-3 { box-shadow: var(--kvyk-elevation-3); }
