/* Tokens, typography and base components for the new app (docs/FRONTEND.md).
   Three themes: :root and [data-theme=light] (white, black, grey), [data-theme=warm] (the earlier
   warm light theme) and [data-theme=dark] (colours from docs/design/mock-*.png). <html data-theme>
   holds the resolved one (theme-boot.js, lib/theme.js). Both light themes are color-scheme: light.
   tests/test_theme_tokens.py reads this file: keep one "--name: value;" per line inside the three
   theme blocks, and keep every token of [data-theme=light] also in [data-theme=warm].
   Layout of the shell lives in shell.css; bigger components in components.css. */
/* Figtree (SIL Open Font License 1.1, assets/fonts/OFL.txt), self-hosted variable font from
   the @fontsource-variable/figtree package: one file per script, weights 300 to 900. */
@font-face {
  font-family: "Figtree"; font-style: normal; font-weight: 300 900; font-display: swap;
  src: url(fonts/figtree-latin-wght-normal.woff2) format("woff2-variations"), url(fonts/figtree-latin-wght-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Figtree"; font-style: normal; font-weight: 300 900; font-display: swap;
  src: url(fonts/figtree-latin-ext-wght-normal.woff2) format("woff2-variations"), url(fonts/figtree-latin-ext-wght-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Non-colour tokens: the same in every theme. */
:root {
  color-scheme: light;
  --font: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* one scale for sizes that must match across pages */
  --content-max: 1180px;    /* .page and every page column (padding included) */
  --ctl-h: 43px;            /* buttons, inputs, selects, search */
  --ctl-h-sm: 34px;         /* small buttons inside rows */
  --ctl-h-lg: 50px;
  --title-card: 19px;       /* page card titles */
  --title-card-sm: 16px;    /* nested or list card titles */
  --label-size: 15px;       /* sentence-case section labels (no uppercase eyebrows) */

  --r-sm: 8px;
  --r: 10px;
  --r-lg: 14px;
  --nav-w: 225px;
  --panel-w: 316px;
  --header-h: 93px;
}



/* Light (the default): white surfaces, black text, greys for lines and secondary text, a black
   primary button. No cream, no beige. The lime --primary stays in the dark theme only. */
:root, [data-theme="light"] {
  color-scheme: light;
  --bg: #FFFFFF;            /* page and right panel */
  --nav-bg: #F7F7F7;
  --header-bg: #FFFFFF;
  --line: #E8E8E8;          /* dividers between regions */
  --border: #E0E0E0;        /* buttons, dividers inside cards */
  --control-border: #737373; /* inputs, selects, checkboxes, switches: >= 3:1 */
  --text: #111111;
  --text-2: #404040;
  --text-3: #666666;        /* >= 4.5:1 on every light surface */
  --brand-icon: #333333;

  --nav-active: #EDEDED;    /* selected nav item: light grey fill with a black bar */
  --nav-active-border: transparent;
  --nav-active-bar: #111111;
  --nav-hover: rgba(0, 0, 0, .05);

  --surface: #FFFFFF;       /* secondary buttons, inputs, zoom controls */
  --surface-2: #F7F7F7;     /* card footer rows */
  --surface-3: #F0F0F0;     /* logo tiles */
  --soft-circle: #F2F2F2;
  --card: rgba(255, 255, 255, .92);
  --card-solid: #FFFFFF;
  --card-border: #E5E5E5;
  --card-shadow: 0 14px 30px rgba(0, 0, 0, .10);
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, .06);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, .20);
  --icon-circle: #EFEFEF;
  --bar-bg: #FAFAFA;        /* bottom bars */

  --primary: #111111;       /* black button, white text */
  --primary-hover: #333333;
  --primary-text: #FFFFFF;
  --primary-glow: none;     /* only lime in dark has a glow */
  --selected-text: var(--text); /* text of a selected segment, tab or choice card */
  --search-border: var(--control-border); /* search boxes: same 3:1 line as every input */
  /* chevron for native selects, drawn in --text-2 */
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23404040' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  --olive: #4D4D4D;         /* the accent line and icon colour: grey here */
  --olive-strong: #4D4D4D;
  --amber: #F0A81C;
  --amber-strong: #D98E10;
  --success: #45B46A;
  --success-bg: #E6F4EA;
  --warning: #8A5A12;
  --warning-bg: #FFF3C4;
  --danger: #C6412F;
  --danger-bg: #FBE7E3;
  --info-bg: #F0F0F0;
  --avatar: #595959;        /* white initials 7:1 */
  --accent-control: #111111; /* checked checkbox, radio, switch */
  --accent-knob: #FFFFFF;
  --on-solid: #FFFFFF;       /* text and icons on solid fills (avatar, done circle, solid danger button) */
  --danger-solid: #C6412F;  /* solid danger button fill: white text 5:1 in every theme */
  --focus-ring: #404040;    /* 2px outline on every focused control */
  --focus: 0 0 0 3px rgba(0, 0, 0, .14);  /* soft glow on focused inputs, with the ring */
  --scrim: rgba(0, 0, 0, .4);
  /* the desert canvas (.sand) in grey: the photo is desaturated, a white veil lifts it */
  --sand-base: #D4D4D4;
  --sand-filter: grayscale(1) brightness(1.08) contrast(.92);
  --sand-overlay: linear-gradient(180deg, rgba(255, 255, 255, .55) 0%, rgba(255, 255, 255, .4) 60%, rgba(245, 245, 245, .3) 100%);
  --sand-blend: normal;
  --skeleton: #EDEDED;
  --skeleton-shine: #F8F8F8;
}

/* Warm light: the earlier light theme, values unchanged. Selectable as "Warm light". Must list
   every token of the light block above (a test checks it), or light values would leak in. */
[data-theme="warm"] {
  color-scheme: light;
  --bg: #FAF8F4;            /* page and right panel */
  --nav-bg: #F7F4EC;
  --header-bg: #FFFFFF;
  --line: #ECE7DB;          /* dividers between regions */
  --border: #E5E1D8;        /* buttons, dividers inside cards */
  --control-border: #8F8A7E; /* inputs, selects, checkboxes, switches: >= 3:1 */
  --text: #1B1B1B;
  --text-2: #3A4557;
  --text-3: #5F6675;        /* >= 4.5:1 on every light surface */
  --brand-icon: #B98E4F;

  --nav-active: #F2F0B8;
  --nav-active-border: transparent;
  --nav-active-bar: transparent;
  --nav-hover: rgba(0, 0, 0, .04);

  --surface: #FFFFFF;       /* secondary buttons, inputs, zoom controls */
  --surface-2: #F5F3EF;     /* card footer rows */
  --surface-3: #F1EEE7;     /* logo tiles */
  --soft-circle: #F3EFE6;
  --card: rgba(255, 255, 255, .9);
  --card-solid: #FFFFFF;
  --card-border: #E9E4DA;
  --card-shadow: 0 14px 30px rgba(120, 95, 60, .14);
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, .06);
  --shadow-lg: 0 24px 60px rgba(60, 45, 20, .22);
  --icon-circle: #FBEBD7;
  --bar-bg: #FCFBF8;        /* bottom bars */

  --primary: #E3ED03;       /* the mock's lime */
  --primary-hover: #D8E200;
  --primary-text: #1B1B1B;
  --primary-glow: 0 0 12px rgba(214, 224, 0, .35); /* only on the screen's one main action (shell.css) */
  --selected-text: var(--text); /* text of a selected segment, tab or choice card */
  --search-border: var(--control-border); /* search boxes: same 3:1 line as every input (was a soft warm line at 1.6:1) */
  /* chevron for native selects, drawn in --text-2 */
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%233A4557' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  --olive: #5E5D26;
  --olive-strong: #5E5D2E;
  --amber: #F0A81C;
  --amber-strong: #D98E10;
  --success: #45B46A;
  --success-bg: #E6F4EA;
  --warning: #8A5A12;
  --warning-bg: #FDF1DC;
  --danger: #C6412F;
  --danger-bg: #FBE7E3;
  --info-bg: #EEF1F6;
  --avatar: #806848;        /* white initials 5.3:1 */
  --accent-control: #5E5D26; /* checked checkbox, radio, switch */
  --accent-knob: #FFFFFF;
  --on-solid: #FFFFFF;       /* text and icons on solid fills (avatar, done circle, solid danger button) */
  --danger-solid: #C6412F;  /* solid danger button fill: white text 5:1 in every theme */
  --focus-ring: #5E5D26;    /* 2px outline on every focused control */
  --focus: 0 0 0 3px rgba(150, 160, 30, .28);  /* soft glow on focused inputs, with the ring */
  --scrim: rgba(27, 24, 16, .38);
  --sand-overlay: linear-gradient(180deg, rgba(250, 246, 240, .45) 0%, rgba(250, 244, 236, .25) 60%, rgba(245, 236, 224, .1) 100%);
  --sand-blend: normal;
  --skeleton: #EFEBE2;
  --skeleton-shine: #F8F5EF;
  --sand-base: #C9B79A;
  --sand-filter: none;
}

[data-theme="dark"] {
  color-scheme: dark;
  --bg: #1C1C16;
  --nav-bg: #23231A;
  --header-bg: #26251D;
  --line: #3A382F;
  --border: #3A382F;
  --text: #F4F2EC;
  --text-2: #BFC1BF;
  --text-3: #9FA29F;
  --control-border: #7A776C;
  --brand-icon: #E8C27E;   /* the mock's gold mark */

  --nav-active: #3B391D;   /* the mock's active nav fill, also selected segments, tabs, cards */
  --nav-active-border: #5A5728;
  --nav-active-bar: #E4F200;
  --nav-hover: rgba(255, 255, 255, .05);

  --surface: #26251F;
  --surface-2: #2A2923;
  --surface-3: #2C2B24;
  --soft-circle: #33322A;
  --card: rgba(31, 30, 26, .92);
  --card-solid: #1F1E1A;
  --card-border: #3A382F;
  --card-shadow: 0 18px 40px rgba(0, 0, 0, .35);
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, .3);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, .5);
  --icon-circle: #3A3524;
  --bar-bg: #211F19;

  --primary: #E4F200;
  --primary-hover: #EEFA3C;
  --primary-text: #1B1B1B;  /* pinned here: the light theme's is white */
  --primary-glow: 0 0 12px rgba(228, 242, 0, .28);
  --selected-text: #E4F200; /* lime text on the selected segment, tab or card */
  --search-border: var(--control-border);
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23BFC1BF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  --olive: #D6CF7A;
  --olive-strong: #5E5D2E;
  --success: #3DD068;
  --success-bg: #1F3322;
  --warning: #E9B04C;
  --warning-bg: #3A2F18;
  --danger: #F07D6B;
  --danger-bg: #3D211C;
  --info-bg: #2A2C2E;
  --avatar: #7A6C4E;
  --accent-control: #E4F200;
  --accent-knob: #1B1B1B;
  --on-solid: #FFFFFF;       /* text and icons on solid fills (avatar, done circle, solid danger button) */
  --danger-solid: #C6412F;  /* solid danger button fill: white text 5:1 in every theme */
  --focus-ring: #E4F200;
  --focus: 0 0 0 3px rgba(228, 242, 0, .2);
  --scrim: rgba(0, 0, 0, .55);
  /* dark desert: the photo gets more contrast (so the pale mountain ridge reads dark against the
     sky, like the mock), then a dusk tint is multiplied over it: dark sky, an orange glow low on
     the left, the ridge band darkest, the sand a warm mid brown that darkens towards the bottom */
  --sand-filter: brightness(.78) contrast(3) saturate(.3);
  --sand-overlay: radial-gradient(ellipse 40% 18% at 8% 25%, rgba(250, 150, 55, .95), rgba(200, 120, 60, 0) 100%),
    linear-gradient(180deg, rgb(66, 60, 54) 0%, rgb(118, 102, 88) 20%, rgb(132, 116, 100) 30%, rgb(116, 102, 88) 55%, rgb(74, 66, 58) 100%);
  --sand-blend: multiply;
  --sand-base: #C9B79A;
  --skeleton: #2C2B24;
  --skeleton-shine: #36352C;
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  font-family: var(--font); font-size: 15px; line-height: 1.45; color: var(--text);
  background: var(--bg); -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
}
a { color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }
img, svg { display: block; }
[hidden] { display: none !important; }
/* One visible focus ring everywhere (2px solid, 6:1 or better); an outline, so it survives
   box-shadow glows (.btn-primary) and Windows forced colours. */
:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
[tabindex="-1"]:focus { outline: none; box-shadow: none; }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -.01em; }
.h1 { font-size: 25px; line-height: 1.2; font-weight: 600; }
.h2 { font-size: 20px; line-height: 1.25; font-weight: 600; }
.h3 { font-size: 17px; line-height: 1.3; font-weight: 500; }
p { margin: 0; }
.muted { color: var(--text-2); }
.faint { color: var(--text-3); }
.small { font-size: 13px; }
.tiny { font-size: 11px; }
.mono { font-family: var(--mono); font-size: 13px; }
.stack { display: flex; flex-direction: column; gap: 12px; }
.stack-lg { display: flex; flex-direction: column; gap: 24px; }
.row { display: flex; align-items: center; gap: 12px; }
.row-wrap { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.spacer { flex: 1 1 auto; }
.grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.ico { flex: none; }

/* Padded page content inside #view (pages that are not a full canvas). */
.page { padding: 32px; max-width: var(--content-max); }
.page-wide { padding: 32px; }

/* The desert canvas background (Flows editor, sign in, Home "Try a question", empty Flows).
   The photo sits in ::before so dark mode can sharpen it (the mountain ridge of the mock) without
   touching the content; the tint sits in ::after. */
.sand { position: relative; background: var(--sand-base); isolation: isolate; }
.sand::before, .sand::after { content: ""; position: absolute; inset: 0; pointer-events: none; z-index: -1; }
.sand::before { background: url("/app/assets/desert.jpg") center 30% / cover no-repeat; filter: var(--sand-filter, none); }
.sand::after { background: var(--sand-overlay); mix-blend-mode: var(--sand-blend); }

/* ---------- buttons ---------- */
/* Heights: --ctl-h (43px) for every normal button and field, --ctl-h-sm (34px) only inside list
   rows, --ctl-h-lg (50px) for a page's single big call to action. All 44px on phones. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; height: var(--ctl-h);
  padding: 0 18px; border-radius: var(--r); border: 1px solid var(--border); background: var(--surface);
  color: var(--text); font-size: 15px; font-weight: 500; white-space: nowrap; cursor: pointer;
  text-decoration: none; transition: background .15s, box-shadow .15s, border-color .15s;
}
.btn:hover { border-color: color-mix(in srgb, var(--border) 60%, var(--text) 25%); }
.btn .ico { width: 17px; height: 17px; }
/* Lime is for the one main action of a screen. */
.btn-primary { background: var(--primary); color: var(--primary-text); border-color: transparent; }
.btn-primary:hover { background: var(--primary-hover); border-color: transparent; }
.btn-primary:focus-visible, .btn:disabled:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.btn-ghost { background: transparent; border-color: transparent; }
.btn-ghost:hover { background: var(--nav-hover); border-color: transparent; }
.btn-danger { color: var(--danger); }
.btn-danger.btn-solid { background: var(--danger-solid); color: var(--on-solid); border-color: transparent; }
.btn-sm { height: var(--ctl-h-sm); padding: 0 12px; font-size: 14px; gap: 8px; border-radius: var(--r-sm); }
.btn-lg { height: var(--ctl-h-lg); padding: 0 24px; font-size: 16px; }
.btn-block { width: 100%; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; box-shadow: none; }
/* Dark: lime at half opacity reads as a lit olive button, so a disabled primary goes neutral. */
[data-theme="dark"] .btn-primary:disabled:not(.is-busy), [data-theme="dark"] .btn-primary[aria-disabled="true"]:not(.is-busy) {
  background: var(--surface-2); color: var(--text-3); border-color: var(--border); opacity: 1;
}
.btn.is-busy { position: relative; color: transparent !important; pointer-events: none; }
.btn.is-busy::after {   /* the same three dots as .spinner, drawn in one box, fading in turn */
  content: ""; position: absolute; width: 34px; height: 8px;
  background: radial-gradient(circle, var(--text-2) 3.5px, transparent 4px) 0 0 / 12px 8px repeat-x;
  -webkit-mask: linear-gradient(90deg, #000 30%, rgba(0,0,0,.3) 50%, #000 70%) 0 0 / 300% 100%;
  mask: linear-gradient(90deg, #000 30%, rgba(0,0,0,.3) 50%, #000 70%) 0 0 / 300% 100%;
  animation: ks-dots-wave 1.4s linear infinite;
}
.btn-primary.is-busy::after { background-image: radial-gradient(circle, var(--primary-text) 3.5px, transparent 4px); }
.icon-btn {
  display: inline-grid; place-items: center; width: 42px; height: 42px; flex: none; padding: 0;
  border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); color: var(--text); cursor: pointer;
}
.icon-btn:hover { border-color: color-mix(in srgb, var(--border) 60%, var(--text) 25%); }
.icon-btn .ico { width: 18px; height: 18px; }
.icon-btn.is-plain { border-color: transparent; background: transparent; }
.icon-btn.is-plain:hover { background: var(--nav-hover); }
.round-btn {
  display: inline-grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; flex: none;
  border: 1px solid var(--border); background: var(--surface); color: var(--text); cursor: pointer; padding: 0;
}
.round-btn .ico { width: 16px; height: 16px; }
.link-btn { border: 0; background: none; padding: 0; color: var(--text); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-3); flex: none; }
.dot.is-on { background: var(--success); }
.dot.is-warn { background: var(--amber); }
.dot.is-bad { background: var(--danger); }
/* Needs attention: orange, the same dot everywhere (lists, tree, pills, the box on a source) */
:root, [data-theme="light"], [data-theme="warm"] { --attn: #E2761B; --attn-bg: #FCEBDC; --attn-text: #8A4510; }
[data-theme="dark"] { --attn: #F29A45; --attn-bg: #3A2716; --attn-text: #F6B77A; }
.dot.is-attn { background: var(--attn); }

/* ---------- inputs ---------- */
.field { display: flex; flex-direction: column; gap: 6px; }
.field-label { font-size: 14px; font-weight: 500; }
.field-help { font-size: 13px; color: var(--text-3); }
.field-error { font-size: 13px; color: var(--danger); }
.input, .select, .textarea {
  width: 100%; height: var(--ctl-h); padding: 0 14px; border: 1px solid var(--control-border); border-radius: var(--r);
  background: var(--surface); color: var(--text); font-size: 15px;
}
.textarea { height: auto; min-height: 96px; padding: 10px 14px; resize: vertical; line-height: 1.45; }
.input::placeholder, .textarea::placeholder { color: var(--text-3); }
/* focused field: the same 2px ring colour as :focus-visible, drawn as border + 1px shadow */
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--focus-ring); box-shadow: 0 0 0 1px var(--focus-ring), var(--focus);
}
.input[aria-invalid="true"], .select[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--danger); }
/* one search box height everywhere */
.search { position: relative; }
.search .ico { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; pointer-events: none; color: var(--text-2); }
.search .input { padding-left: 40px; height: var(--ctl-h); border-color: var(--search-border); }
.search .input:focus { border-color: var(--focus-ring); }
/* native selects: no browser chevron, the app's own on the right */
.select, select.input {
  appearance: none; -webkit-appearance: none; padding-right: 40px; cursor: pointer;
  background-image: var(--chevron); background-repeat: no-repeat; background-position: right 12px center; background-size: 18px 18px;
}
.select:disabled, select.input:disabled { cursor: not-allowed; }
select[multiple].select, select[size].select { background-image: none; padding-right: 14px; }

/* checkboxes and radios: native, tinted with the accent (olive in light, lime in dark) */
input[type="checkbox"]:not(.switch), input[type="radio"] {
  width: 18px; height: 18px; margin: 0; flex: none; accent-color: var(--accent-control); cursor: pointer;
}
input[type="checkbox"]:not(.switch):disabled, input[type="radio"]:disabled { cursor: not-allowed; }
.check { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; }
.check input { width: 18px; height: 18px; accent-color: var(--accent-control); }
/* switches: off = grey track with a 3:1 edge, on = accent track */
.switch {
  position: relative; width: 42px; height: 26px; flex: none; appearance: none; -webkit-appearance: none; margin: 0;
  border-radius: 13px; border: 1.5px solid var(--control-border); background: var(--surface-3); cursor: pointer;
  transition: background .15s, border-color .15s;
}
.switch::after {
  content: ""; position: absolute; top: 2.5px; left: 2.5px; width: 18px; height: 18px; border-radius: 50%;
  background: var(--control-border); transition: transform .15s, background .15s;
}
.switch:checked { background: var(--accent-control); border-color: var(--accent-control); }
.switch:checked::after { transform: translateX(16px); background: var(--accent-knob); }
.switch:disabled { opacity: .5; cursor: not-allowed; }

/* phones: every control is a 44px touch target */
@media (max-width: 820px) {
  :root { --ctl-h: 44px; --ctl-h-sm: 44px; --ctl-h-lg: 48px; }
  .icon-btn { width: 44px; height: 44px; }
}

@keyframes spin { to { transform: rotate(360deg); } }
/* ai.chat2.com's typing indicator, exactly: 6 px dots 4 px apart, 1.4 s, 0.2 s apart, rise 8 px. */
@keyframes ks-dot { 0%, 60%, 100% { transform: translateY(0); opacity: 0.6; } 30% { transform: translateY(-8px); opacity: 1; } }
@keyframes ks-pulse-slow { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@keyframes ks-dots-wave { from { -webkit-mask-position: 100% 0; mask-position: 100% 0; } to { -webkit-mask-position: 0 0; mask-position: 0 0; } }
@keyframes shine { 0% { background-position: -200px 0; } 100% { background-position: calc(200px + 100%) 0; } }
/* Reduced motion: animations jump to their end ONCE (iteration 1), so nothing ever flickers on and off. */
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; } }
/* The typing dots and slow status pulses are gentle, so they keep moving with reduced motion too
   (ai.chat2.com's typing dots do the same). */
@media (prefers-reduced-motion: reduce) {
  .spinner > span, .home-typing span, .btn.is-busy::after,
  .srcnav-status.is-tone-reading .dot, .ks-pilot-dot { animation-duration: 1.4s !important; animation-iteration-count: infinite !important; }
  .srcnav-status.is-tone-reading .dot { animation-duration: 2.8s !important; }
}


