/* AUVOX design system - "Sales Lab".
   Source of truth: AUREVIA/AUVOX/DESIGN/brand-spec.md and the :root of the old
   AUVOX public/style.css. The token NAMES below are the ones this app was built
   on (it began as a fork of AUMENTOR), so every screen re-colours from here and
   nothing else has to change. Only the values are AUVOX's.

   Three rules hold across the whole app:
     Green is the brand. Solid green marks the primary action and where you are.
     The bright logo green (--live) means "live / recording now" and is only ever
     a small signal, never a large fill.
     Gold (--accent) marks the one thing on a screen that needs a person, and
     premium/achievement details. If gold is everywhere it stops meaning anything.
     Nothing is drawn as a filled bar unless the number behind it is real. A missing
     measure is drawn as a hatched slot, never as an empty bar that reads as zero.

   Text that sits ON a solid brand fill uses --on-brand, never #fff: in the dark
   theme the brand goes bright and the label on it goes dark. */

/* The AUVOX faces, self-hosted. They are the Google Fonts files (IBM Plex Sans
   Thai, Noto Sans Thai, IBM Plex Mono; thai + latin subsets only), served from
   /assets/fonts because the page's Content-Security-Policy allows fonts and
   styles from 'self' only - a fonts.googleapis.com link is refused and logs a
   console error on every page. assets/ is open before sign-in, so the login
   page gets them too. */
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url("/assets/fonts/ibm-plex-mono-400-latin.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: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url("/assets/fonts/ibm-plex-mono-500-latin.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: 'IBM Plex Sans Thai'; font-style: normal; font-weight: 400; font-display: swap; src: url("/assets/fonts/ibm-plex-sans-thai-400-thai.woff2") format('woff2'); unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC; }
@font-face { font-family: 'IBM Plex Sans Thai'; font-style: normal; font-weight: 400; font-display: swap; src: url("/assets/fonts/ibm-plex-sans-thai-400-latin.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: 'IBM Plex Sans Thai'; font-style: normal; font-weight: 500; font-display: swap; src: url("/assets/fonts/ibm-plex-sans-thai-500-thai.woff2") format('woff2'); unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC; }
@font-face { font-family: 'IBM Plex Sans Thai'; font-style: normal; font-weight: 500; font-display: swap; src: url("/assets/fonts/ibm-plex-sans-thai-500-latin.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: 'IBM Plex Sans Thai'; font-style: normal; font-weight: 600; font-display: swap; src: url("/assets/fonts/ibm-plex-sans-thai-600-thai.woff2") format('woff2'); unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC; }
@font-face { font-family: 'IBM Plex Sans Thai'; font-style: normal; font-weight: 600; font-display: swap; src: url("/assets/fonts/ibm-plex-sans-thai-600-latin.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: 'IBM Plex Sans Thai'; font-style: normal; font-weight: 700; font-display: swap; src: url("/assets/fonts/ibm-plex-sans-thai-700-thai.woff2") format('woff2'); unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC; }
@font-face { font-family: 'IBM Plex Sans Thai'; font-style: normal; font-weight: 700; font-display: swap; src: url("/assets/fonts/ibm-plex-sans-thai-700-latin.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: 'Noto Sans Thai'; font-style: normal; font-weight: 400 700; font-display: swap; src: url("/assets/fonts/noto-sans-thai-400-700-thai.woff2") format('woff2'); unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC; }
@font-face { font-family: 'Noto Sans Thai'; font-style: normal; font-weight: 400 700; font-display: swap; src: url("/assets/fonts/noto-sans-thai-400-700-latin.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; }

:root {
  color-scheme: light;

  /* brand - green Sales Lab */
  --brand: oklch(51% 0.17 144);
  --brand-deep: oklch(36% 0.1 151);
  /* What a solid brand button goes when the pointer is on it. */
  --brand-hover: oklch(45% 0.155 145);
  --brand-ink: oklch(32% 0.085 152);
  --brand-soft: oklch(95.8% 0.032 148);
  --brand-line: oklch(87.5% 0.065 148);
  --on-brand: #FFFFFF;
  /* The logo's own green. Live/realtime signal only - small dots, rings, bars. */
  --live: oklch(84.9% 0.288 142.5);

  /* gold - attention + premium detail (from the logo emblem) */
  --accent: oklch(72% 0.14 82);
  --accent-soft: oklch(96.4% 0.04 92);
  --accent-ink: oklch(44% 0.095 74);
  --accent-line: oklch(86.5% 0.08 88);
  --on-accent: oklch(24% 0.05 70);
  --gold: oklch(70.9% 0.137 81.5);
  --gold-light: oklch(92.4% 0.124 96.3);
  --gold-deep: oklch(56% 0.12 74);

  /* The coloured band at the top of a screen. Stays dark in both themes so the
     white copy on it always reads. */
  --band: oklch(33% 0.085 152);
  --band-2: oklch(42% 0.125 147);
  --band-ink: #FFFFFF;

  /* Neutrals carrying a trace of the brand hue, so the greys look chosen rather
     than borrowed. The page sits a step below white on purpose: with a light rail
     and white cards, a near-white page leaves nothing to lift off. */
  --bg: oklch(97.6% 0.007 140);
  --surface: oklch(100% 0 0);
  --surface-2: oklch(98.6% 0.005 140);
  --sunken: oklch(95.4% 0.009 145);
  --line: oklch(91.1% 0.012 153.7);
  --line-soft: oklch(94.6% 0.008 150);
  --ink-1: oklch(18% 0.02 158);
  --ink: oklch(23% 0.022 158.5);
  --ink-2: oklch(38% 0.022 157);
  --ink-3: oklch(52% 0.021 155.4);
  --ink-4: oklch(66% 0.017 155);

  /* status - hues kept apart from the brand green and the gold */
  --good: oklch(52% 0.12 165);
  --good-soft: oklch(95.5% 0.035 165);
  --warn: oklch(55% 0.135 58);
  --warn-soft: oklch(96% 0.04 70);
  --warn-ink: oklch(40% 0.09 58);
  --bad: oklch(55% 0.19 28);
  --bad-soft: oklch(95.8% 0.025 25);
  --bad-ink: oklch(40% 0.13 28);
  --info: oklch(54% 0.13 250);
  --info-soft: oklch(95.8% 0.025 250);

  /* the two kinds of bot - one accent each, everywhere a bot is shown */
  --kind-practice: var(--brand);
  --kind-practice-soft: var(--brand-soft);
  --kind-practice-ink: var(--brand-ink);
  --kind-mentor: oklch(62% 0.13 78);
  --kind-mentor-soft: var(--accent-soft);
  --kind-mentor-ink: var(--accent-ink);

  /* the five index sub-scores keep one colour each, everywhere they appear */
  --sub-conversation: oklch(51% 0.17 144);
  --sub-followthrough: oklch(66% 0.14 78);
  --sub-goal: oklch(55% 0.11 200);
  --sub-capability: oklch(52% 0.15 300);
  --sub-relationship: oklch(56% 0.13 250);

  --focus: color-mix(in srgb, var(--brand) 32%, transparent);

  /* AUVOX radius scale: 18 cards, 12 controls, 24 bands, pill buttons. */
  --radius: 18px;
  --radius-sm: 12px;
  --radius-lg: 24px;
  --radius-pill: 999px;

  /* Shadows tinted with the brand ink rather than neutral black, spread wide and
     soft, so a card looks lit rather than outlined. */
  --shadow-sm: 0 1px 2px oklch(23% 0.022 158.5 / .05), 0 2px 8px oklch(23% 0.022 158.5 / .04);
  --shadow: 0 2px 6px oklch(23% 0.022 158.5 / .05), 0 12px 28px oklch(23% 0.022 158.5 / .07);
  --shadow-lg: 0 18px 45px oklch(23% 0.022 158.5 / .14);
  --shadow-brand: 0 8px 18px color-mix(in srgb, var(--brand) 26%, transparent);

  --rail: 240px;
  --topbar: 62px;
  --page-max: 1180px;

  /* AUVOX type: IBM Plex Sans Thai for display, Noto Sans Thai for reading.
     Loaded from Google Fonts in index.html / login.html; the local Thai faces
     behind them keep the page readable offline. */
  --font: "Noto Sans Thai", "Leelawadee UI", "Segoe UI", Tahoma, system-ui, sans-serif;
  --font-display: "IBM Plex Sans Thai", "Noto Sans Thai", "Leelawadee UI", "Segoe UI", sans-serif;
  --font-num: "IBM Plex Sans Thai", "Segoe UI", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", "Cascadia Mono", Consolas, ui-monospace, monospace;
}

/* Dark: a deep green-black, not a neutral slate, so the dark theme is the same
   product as the light one. Brand fills go bright (the logo green, toned down)
   and the label on them goes dark - --on-brand flips with it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --brand: oklch(74% 0.175 145);
    --brand-deep: oklch(30% 0.07 152);
    --brand-hover: oklch(80% 0.17 145);
    --brand-ink: oklch(86% 0.1 145);
    --brand-soft: oklch(27% 0.045 150);
    --brand-line: oklch(38% 0.07 149);
    --on-brand: oklch(17% 0.035 150);
    --live: oklch(84.9% 0.288 142.5);

    --accent: oklch(80% 0.13 85);
    --accent-soft: oklch(27% 0.04 85);
    --accent-ink: oklch(87% 0.1 90);
    --accent-line: oklch(40% 0.07 84);
    --on-accent: oklch(20% 0.04 70);
    --gold: oklch(78% 0.125 86);
    --gold-light: oklch(92% 0.1 96);
    --gold-deep: oklch(60% 0.12 76);

    --band: oklch(25% 0.05 152);
    --band-2: oklch(33% 0.085 149);
    --band-ink: #FFFFFF;

    --bg: oklch(16% 0.016 155);
    --surface: oklch(20.5% 0.02 155);
    --surface-2: oklch(23% 0.021 155);
    --sunken: oklch(14.5% 0.015 155);
    --line: oklch(31% 0.024 155);
    --line-soft: oklch(26% 0.02 155);
    --ink-1: oklch(98% 0.008 140);
    --ink: oklch(95% 0.012 140);
    --ink-2: oklch(83% 0.02 145);
    --ink-3: oklch(70% 0.022 150);
    --ink-4: oklch(58% 0.02 152);

    --good: oklch(75% 0.13 165);
    --good-soft: oklch(26% 0.04 165);
    --warn: oklch(77% 0.13 65);
    --warn-soft: oklch(27% 0.045 65);
    --warn-ink: oklch(85% 0.11 70);
    --bad: oklch(70% 0.16 28);
    --bad-soft: oklch(26% 0.05 25);
    --bad-ink: oklch(82% 0.1 28);
    --info: oklch(72% 0.12 250);
    --info-soft: oklch(26% 0.04 250);

    --kind-mentor: oklch(80% 0.13 85);

    --sub-conversation: oklch(74% 0.175 145);
    --sub-followthrough: oklch(80% 0.13 85);
    --sub-goal: oklch(74% 0.11 200);
    --sub-capability: oklch(72% 0.13 300);
    --sub-relationship: oklch(72% 0.12 250);

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow: 0 2px 10px rgba(0, 0, 0, .45);
    --shadow-lg: 0 14px 36px rgba(0, 0, 0, .55);
    --shadow-brand: 0 8px 22px color-mix(in srgb, var(--brand) 22%, transparent);
  }
}

:root[data-theme="dark"] {
  /* Kept in step with the media-query block above. */
  color-scheme: dark;
  --brand: oklch(74% 0.175 145);
  --brand-deep: oklch(30% 0.07 152);
  --brand-hover: oklch(80% 0.17 145);
  --brand-ink: oklch(86% 0.1 145);
  --brand-soft: oklch(27% 0.045 150);
  --brand-line: oklch(38% 0.07 149);
  --on-brand: oklch(17% 0.035 150);
  --live: oklch(84.9% 0.288 142.5);

  --accent: oklch(80% 0.13 85);
  --accent-soft: oklch(27% 0.04 85);
  --accent-ink: oklch(87% 0.1 90);
  --accent-line: oklch(40% 0.07 84);
  --on-accent: oklch(20% 0.04 70);
  --gold: oklch(78% 0.125 86);
  --gold-light: oklch(92% 0.1 96);
  --gold-deep: oklch(60% 0.12 76);

  --band: oklch(25% 0.05 152);
  --band-2: oklch(33% 0.085 149);
  --band-ink: #FFFFFF;

  --bg: oklch(16% 0.016 155);
  --surface: oklch(20.5% 0.02 155);
  --surface-2: oklch(23% 0.021 155);
  --sunken: oklch(14.5% 0.015 155);
  --line: oklch(31% 0.024 155);
  --line-soft: oklch(26% 0.02 155);
  --ink-1: oklch(98% 0.008 140);
  --ink: oklch(95% 0.012 140);
  --ink-2: oklch(83% 0.02 145);
  --ink-3: oklch(70% 0.022 150);
  --ink-4: oklch(58% 0.02 152);

  --good: oklch(75% 0.13 165);
  --good-soft: oklch(26% 0.04 165);
  --warn: oklch(77% 0.13 65);
  --warn-soft: oklch(27% 0.045 65);
  --warn-ink: oklch(85% 0.11 70);
  --bad: oklch(70% 0.16 28);
  --bad-soft: oklch(26% 0.05 25);
  --bad-ink: oklch(82% 0.1 28);
  --info: oklch(72% 0.12 250);
  --info-soft: oklch(26% 0.04 250);

  --kind-mentor: oklch(80% 0.13 85);

  --sub-conversation: oklch(74% 0.175 145);
  --sub-followthrough: oklch(80% 0.13 85);
  --sub-goal: oklch(74% 0.11 200);
  --sub-capability: oklch(72% 0.13 300);
  --sub-relationship: oklch(72% 0.12 250);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow: 0 2px 10px rgba(0, 0, 0, .45);
  --shadow-lg: 0 14px 36px rgba(0, 0, 0, .55);
  --shadow-brand: 0 8px 22px color-mix(in srgb, var(--brand) 22%, transparent);
}

/* ------------------------------------------------------------------ reset */

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

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

[hidden] { display: none !important; }

img, svg { max-width: 100%; }

/* Thai tone marks sit above the cap height, so headings carry more leading than a
   Latin-only scale would. Display face for headings, reading face for the rest. */
h1, h2, h3, h4 { margin: 0; font-family: var(--font-display); font-weight: 600; line-height: 1.4; letter-spacing: -.005em; }
h1 { font-size: 24px; letter-spacing: -.015em; }
h2 { font-size: 17.5px; }
h3 { font-size: 15px; line-height: 1.45; }
h4 { font-size: 14px; line-height: 1.45; }
p { margin: 0 0 10px; }
p:last-child { margin-bottom: 0; }

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--brand) 70%, var(--surface));
  outline-offset: 2px;
  border-radius: 6px;
}

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

/* ------------------------------------------------------------------ shell */

.shell {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  min-height: 100dvh;
}

/* The rail is light, like the AUVOX Sales Lab mockups: hairline divider, no
   stacked cards, the gold mark carrying the brand. */
.rail {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 12px;
  background: var(--surface);
  border-right: 1px solid var(--line);
  color: var(--ink);
  overflow-y: auto;
}

/* Scoped to the rail. An unscoped `.brand` also matched `class="tag brand"`,
   which stretched every brand-coloured tag to the full width of its row. */
.rail .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px 14px;
  background: none;
  border: 0;
  color: inherit;
  cursor: pointer;
  text-align: left;
  width: 100%;
}
/* The supplied lockup, not type set to look like it. */
.rail .brand img { height: 34px; width: auto; object-fit: contain; flex: none; }
.brand-sub {
  display: block;
  margin-top: 3px;
  font-size: 10.5px;
  letter-spacing: .02em;
  color: var(--ink-3);
}

/* Dark mode gets the other cut of the same artwork: gold mark with a gold
   wordmark (the light cut sets the wordmark in deep green ink). Both files are
   cut from AUVOX/ICON/logo.png; neither is type set to imitate it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .rail .brand img { content: url("/assets/lockup-light.png"); }
}
:root[data-theme="dark"] .rail .brand img { content: url("/assets/lockup-light.png"); }

.rail-group {
  margin: 14px 10px 5px;
  font-size: 10.5px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-4);
  font-weight: 640;
}

.nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  min-height: 40px;
  padding: 8px 11px;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-size: 13.5px;
  cursor: pointer;
  text-align: left;
  transition: background .12s ease, color .12s ease;
}
.nav-link svg { width: 18px; height: 18px; flex: none; color: var(--ink-4); transition: color .12s ease; }
.nav-link:hover { background: var(--sunken); color: var(--ink); }
.nav-link:hover svg { color: var(--ink-2); }
/* Where you are is a solid block of brand green. A tint would be quieter, but on a
   rail this long the eye should find the current place without looking for it. */
.nav-link.active {
  background: var(--brand);
  color: var(--on-brand);
  font-weight: 620;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--brand) 32%, transparent);
}
.nav-link.active svg { color: var(--on-brand); }
.nav-link.active:hover { background: var(--brand-hover); color: var(--on-brand); }
.nav-link.active .pip { background: var(--on-brand); color: var(--brand); }
.nav-link .pip {
  margin-left: auto;
  min-width: 19px;
  height: 19px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 11px;
  font-weight: 700;
  display: grid;
  place-items: center;
}
/* Long labels wrap, as they always have. They must not push the chevron of a
   parent row off the rail, which is what min-width:0 is for. */
.nav-link .nav-label { min-width: 0; overflow-wrap: anywhere; }

/* A rail entry that is both a screen and a group. Two buttons, one row: the
   label goes to the screen, the chevron opens what is under it. */
/* Stretched rather than centred, so the chevron is as tall as the row it sits
   in. On a phone a 30px square is a target you miss. */
.nav-row { display: flex; align-items: stretch; gap: 2px; }
.nav-row > .nav-link { flex: 1; min-width: 0; }
.nav-twist {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink-4);
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.nav-twist svg { width: 16px; height: 16px; }
.nav-twist:hover:not(:disabled) { background: var(--sunken); color: var(--ink-2); }
.nav-twist:disabled { cursor: default; opacity: .45; }

/* [hidden] alone loses to a display rule, so the closed state is spelled out. */
.nav-sub { display: grid; gap: 2px; margin: 2px 0 2px 19px; padding-left: 9px; border-left: 1px solid var(--line); }
.nav-sub[hidden] { display: none; }
.nav-link.is-sub { font-size: 13px; padding: 7px 10px; gap: 9px; }
.nav-link.is-sub svg { width: 16px; height: 16px; }

.rail-foot { margin-top: auto; padding-top: 12px; }
.rail-version { padding: 8px 12px 2px; font-size: 11px; color: var(--ink-4); letter-spacing: .04em; }

.main { display: flex; flex-direction: column; min-width: 0; }

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  height: var(--topbar);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 20px;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.crumb { font-family: var(--font-display); font-weight: 600; font-size: 15.5px; }
.crumb-sub { color: var(--ink-3); font-weight: 400; font-size: 13px; }
.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.page {
  flex: 1;
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 26px 24px 72px;
}

.page-head {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}
.page-head .lede { color: var(--ink-3); margin-top: 3px; max-width: 62ch; }
.page-head-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* The brand band. One per screen at most, at the top. Deep forest green in both
   themes (--band), so the white copy on it always reads. */
.hero {
  position: relative;
  overflow: hidden;
  padding: 22px 24px;
  margin-bottom: 18px;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(120% 140% at 100% 0%, color-mix(in srgb, var(--gold) 16%, transparent), transparent 46%),
    linear-gradient(135deg, var(--band) 0%, var(--band-2) 100%);
  color: var(--band-ink);
  box-shadow: 0 12px 30px color-mix(in srgb, var(--band) 30%, transparent);
}
.hero::after {
  content: "";
  position: absolute;
  right: -60px;
  top: -80px;
  width: 280px;
  height: 280px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, .12), transparent 65%);
  pointer-events: none;
}
.hero h1, .hero h2 { color: var(--band-ink); }
.hero p { color: rgba(255, 255, 255, .86); max-width: 62ch; }
/* The primary action on the band is gold - the metallic logo gold, top-lit - which
   is the one place gold fills a button: on the green band it is the thing that
   wants a person. The `.btn.primary` rule is declared later in this file, so these
   have to name both classes to win. */
.hero .btn, .hero .btn.primary {
  background: linear-gradient(180deg, var(--gold-light) -40%, var(--gold) 55%, var(--gold-deep) 140%);
  border-color: color-mix(in srgb, var(--gold) 80%, #000);
  color: var(--on-accent);
  font-weight: 660;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 6px 16px rgba(0, 0, 0, .2);
}
.hero .btn:hover, .hero .btn.primary:hover { filter: brightness(1.06); }
.hero .btn svg { color: var(--on-accent); }
/* A second, quieter action on the band, when there is one. */
.hero .btn.ghost, .hero .btn.ghost:hover {
  background: rgba(255, 255, 255, .14);
  border-color: rgba(255, 255, 255, .28);
  color: #fff;
  box-shadow: none;
}
.hero .btn.ghost svg { color: #fff; }
/* The band, built on the supplied artwork.
   The picture already carries a plain deep-green field on its left, so the
   copy sits on that field and the same green continues behind the card as a
   background colour. That way the panel never runs out on a wide screen and
   there is no seam where the image stops. */
.hero.banner {
  padding: 0;
  background-color: var(--band);
  background-image:
    linear-gradient(90deg, var(--band) 0%, var(--band) 30%, color-mix(in srgb, var(--band) 70%, transparent) 46%, transparent 66%),
    url("/assets/art/banner-1600.webp");
  background-repeat: no-repeat;
  background-position: left center, right center;
  background-size: 100% 100%, auto 100%;
  min-height: 268px;
  display: flex;
  align-items: center;
}
.hero.banner::after { display: none; }
.hero.banner .hero-body {
  /* Kept inside the narrowest part of the diagonal, which is about 39% of the
     artwork at its bottom edge. Anything wider runs over the photograph. */
  width: min(37%, 460px);
  padding: 26px 0 26px 30px;
}
@media (max-width: 1080px) {
  .hero.banner .hero-body { width: min(46%, 430px); }
}
@media (max-width: 860px) {
  /* The diagonal cannot do its job at this width, so the band stacks: a taller
     crop centred on the person above, the copy on the panel green below. */
  .hero.banner {
    display: block;
    min-height: 0;
    background-image: url("/assets/art/banner-tall-900.webp");
    background-position: center top;
    background-size: 100% auto;
    padding-top: 58%;
  }
  .hero.banner .hero-body {
    width: auto;
    padding: 20px 22px 24px;
    background: linear-gradient(180deg, color-mix(in srgb, var(--band) 86%, transparent), var(--band) 22%);
  }
}

/* The copy on the band, arranged the way the reference does it: a small line
   above, the thing itself, one line of explanation, then a single action. */
.hero-eyebrow {
  display: block;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .72);
  margin-bottom: 8px;
}
.hero-title { font-size: 26px; line-height: 1.35; margin: 0 0 6px; }
@media (max-width: 860px) { .hero-title { font-size: 22px; } }
.hero-lede { font-size: 14px; margin-bottom: 16px; }
/* The action on the band is white, not brand green: green on the green panel has
   almost no edge against what it sits on. The ink stays the light-theme deep
   green in both themes because the plate under it is always white. */
.hero .btn.on-band {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: oklch(36% 0.1 151);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
}
.hero .btn.on-band svg { color: oklch(36% 0.1 151); }
.hero .btn.on-band:hover { background: oklch(96% 0.03 148); border-color: oklch(96% 0.03 148); }

/* The arrow sits a little away from the label and leans into it on hover, which
   is the whole animation this button needs. */
.btn-arrow { display: inline-flex; margin-left: 2px; transition: transform .15s ease; }
.btn:hover .btn-arrow { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) { .btn:hover .btn-arrow { transform: none; } }

/* The journey. Circular nodes on a single connecting line, which is how a
   sequence of stages reads at a glance; a row of equal boxes does not. */
.stepper { display: flex; list-style: none; margin: 0; padding: 0; gap: 0; }
.step {
  position: relative;
  flex: 1;
  min-width: 0;
  text-align: center;
  padding: 0 6px;
}
.step::before {
  content: "";
  position: absolute;
  top: 23px;
  left: calc(-50% + 23px);
  right: calc(50% + 23px);
  height: 2px;
  background: var(--line);
}
.step:first-child::before { display: none; }
.step.done::before, .step.current::before { background: var(--brand-line); }
.step-node {
  position: relative;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin: 0 auto 9px;
  border-radius: 50%;
  background: var(--sunken);
  color: var(--ink-4);
  border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--line);
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 15px;
}
.step-node svg { width: 20px; height: 20px; }
.step.done .step-node { background: var(--good-soft); color: var(--good); box-shadow: 0 0 0 1px color-mix(in srgb, var(--good) 34%, transparent); }
.step.current .step-node { background: var(--brand); color: var(--on-brand); box-shadow: 0 0 0 4px var(--brand-soft); }
.step-label { display: block; font-size: 13px; font-weight: 620; color: var(--ink); }
.step.locked .step-label { color: var(--ink-3); }
.step-sub { display: block; font-size: 11.5px; color: var(--ink-3); margin-top: 1px; }
.step .tag { margin-top: 7px; }
@media (max-width: 720px) {
  .stepper { flex-wrap: wrap; gap: 14px 0; }
  .step { flex: 0 0 33.333%; }
  .step::before { display: none; }
}

/* A single number, drawn as a ring rather than printed in a box. */
.donut {
  --pct: 0;
  --donut-size: 112px;
  --donut-colour: var(--brand);
  position: relative;
  width: var(--donut-size);
  height: var(--donut-size);
  border-radius: 50%;
  display: grid;
  place-items: center;
  /* place-items centres each row inside its own track; it does not centre the
     tracks themselves. With a value and a caption the two rows are auto-sized and
     align-content falls back to start, so the number sat in the top half of the
     ring instead of the middle of it. */
  align-content: center;
  flex: none;
  background: conic-gradient(var(--donut-colour) calc(var(--pct) * 1%), var(--sunken) 0);
  transition: background .5s cubic-bezier(.2, .8, .3, 1);
}
.donut::before {
  content: "";
  position: absolute;
  inset: 12px;
  border-radius: 50%;
  background: var(--surface);
}
.donut-value {
  position: relative;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 24px;
  font-weight: 700;
  line-height: 1;
}
.donut-sub { position: relative; font-size: 11px; color: var(--ink-3); margin-top: 2px; }
/* Nothing measured is a dashed ring, never a ring at zero. */
.donut.is-missing { background: none; border: 2px dashed var(--line); }
.donut.is-missing::before { inset: 0; background: none; }
.donut.is-missing .donut-value { font-size: 12px; font-weight: 600; color: var(--ink-3); padding: 0 12px; text-align: center; }

.hero-row { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.hero-row .spacer { margin-left: auto; }

/* Text and chrome inherited from the light surfaces have to be re-pointed, or
   they arrive on the band as grey on green and disappear. */
.hero .muted, .hero .small.muted { color: rgba(255, 255, 255, .72); }
.hero .card-head h2, .hero .card-head h3 { color: rgba(255, 255, 255, .88); }
.hero .card-head svg { color: rgba(255, 255, 255, .7); }
.hero .tag {
  background: rgba(255, 255, 255, .16);
  color: var(--band-ink);
  border: 1px solid rgba(255, 255, 255, .2);
}
.hero .tag.accent { background: var(--gold); color: var(--on-accent); border-color: var(--gold); }
.hero .home-meta-item .k { color: rgba(255, 255, 255, .64); }
.hero .home-meta-item .v { color: var(--band-ink); }
.hero a { color: var(--band-ink); text-decoration: underline; }

.view { display: none; }
.view.active { display: block; }

/* ---------------------------------------------------------------- controls */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 38px;
  padding: 0 17px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background .16s cubic-bezier(.23, 1, .32, 1), border-color .16s ease, box-shadow .16s ease, transform .06s ease;
}
/* An icon inside a button is always 16px, whatever size the icon() helper drew
   it at - a 24px glyph in a 38px pill reads as a sticker, not a label. */
.btn svg { width: 16px; height: 16px; flex: none; display: block; }
/* The icon() helper wraps its svg in a span. Left inline, that span takes the
   text's line box (22px in Noto Sans Thai) and the 16px glyph sits on its top
   edge, 3px above the label's centre. As a flex box it shrinks to the glyph. */
.btn > span:has(> svg) { display: inline-flex; align-items: center; justify-content: center; }
.btn:hover { background: var(--surface-2); border-color: var(--ink-4); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .5; cursor: not-allowed; }

.btn.primary { background: var(--brand); border-color: var(--brand); color: var(--on-brand); box-shadow: var(--shadow-brand); }
.btn.primary:hover { background: var(--brand-hover); border-color: var(--brand-hover); }

.btn.accent { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.accent:hover { filter: brightness(.95); }

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

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

.btn.sm { min-height: 30px; padding: 0 12px; font-size: 12.5px; }
.btn.lg { min-height: 46px; padding: 0 24px; font-size: 15px; }
.btn.icon { padding: 0; width: 36px; }
.btn.icon.sm { width: 30px; }

.btn-row { display: flex; gap: 8px; flex-wrap: wrap; }

.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.field > label { font-weight: 600; font-size: 13px; }
.field .help { color: var(--ink-3); font-size: 12.5px; }
.field .err { color: var(--bad); font-size: 12.5px; }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="date"], input[type="search"], select, textarea {
  width: 100%;
  min-height: 38px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
}
textarea { min-height: 84px; resize: vertical; line-height: 1.55; }
input:focus, select:focus, textarea:focus { border-color: var(--brand); outline: 2px solid var(--focus); outline-offset: 0; }
input::placeholder, textarea::placeholder { color: var(--ink-4); }
select { appearance: none; padding-right: 30px;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23738279' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center; background-size: 16px; }

.check { display: flex; align-items: flex-start; gap: 9px; cursor: pointer; padding: 5px 0; }

/* The repair rules: "what it heard" on the left, "what was said" on the right,
   and on a phone the arrow turns and the pair stacks rather than shrinking to
   two unusable boxes. */
.rule-list { display: grid; gap: 8px; margin-bottom: 8px; }
.rule-row { display: grid; grid-template-columns: 1fr auto 1fr auto; gap: 8px; align-items: center; }
.rule-row input { min-width: 0; }
@media (max-width: 560px) {
  .rule-row { grid-template-columns: 1fr auto; }
  .rule-row > span { justify-self: center; transform: rotate(90deg); }
}
.check input { width: 16px; height: 16px; margin: 2px 0 0; accent-color: var(--brand); flex: none; }
.check .check-body { display: flex; flex-direction: column; gap: 2px; }
.check .check-body small { color: var(--ink-3); }

.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap: 0 16px; }

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

.card {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 20px 22px;
  box-shadow: var(--shadow-sm);
}
.card + .card { margin-top: 16px; }
.card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.card-head svg { color: var(--ink-4); }
.card-head h2, .card-head h3 { margin: 0; }
.card-head .spacer { margin-left: auto; }

.cards { display: grid; gap: 16px; }
.cards.two { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.cards.three { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

.tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  /* A tag is often a direct child of a flex row, where it would otherwise be
     handed the leftover space and stretch across the whole line. */
  width: max-content;
  max-width: 100%;
  flex: 0 0 auto;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--sunken);
  color: var(--ink-2);
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.tag.brand { background: var(--brand-soft); color: var(--brand-ink); }
/* A tag that holds a sentence or a name (an outcome, a customer name) wraps
   instead of pushing the card wider than a phone. */
.tag.wrap { white-space: normal; overflow-wrap: anywhere; line-height: 1.4; padding: 3px 10px; border-radius: 12px; min-width: 0; }
.tag.good { background: var(--good-soft); color: var(--good); }
.tag.warn { background: var(--warn-soft); color: var(--warn); }
.tag.bad { background: var(--bad-soft); color: var(--bad); }
.tag.accent { background: var(--accent-soft); color: var(--accent-ink); }

.muted { color: var(--ink-3); }
.small { font-size: 12.5px; }
.num { font-family: var(--font-num); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ tables */

.table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.table th {
  text-align: left;
  font-size: 11.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 640;
  padding: 0 10px 8px;
  white-space: nowrap;
}
.table td { padding: 10px; border-top: 1px solid var(--line-soft); vertical-align: middle; }
.table tr:hover td { background: var(--surface-2); }
.table-wrap { overflow-x: auto; }

/* --------------------------------------------------- the measurement widgets */

/* A sub-score bar. When the value is null the track is hatched, which is the
   visual difference between "we have not measured this" and "this scored zero".
   Every dashboard that blurs those two eventually gets somebody judged unfairly. */
.meter { display: grid; grid-template-columns: 1fr auto; gap: 4px 10px; align-items: center; margin-bottom: 9px; }
.meter-label { font-size: 12.5px; color: var(--ink-2); }
.meter-value { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-weight: 680; font-size: 13.5px; }
.meter-track {
  grid-column: 1 / -1;
  height: 7px;
  border-radius: 4px;
  background: var(--sunken);
  overflow: hidden;
}
.meter-fill { height: 100%; border-radius: 4px; background: var(--brand); transition: width .35s cubic-bezier(.2, .8, .3, 1); }
.meter.is-missing .meter-track {
  background-image: repeating-linear-gradient(135deg, var(--line) 0 5px, transparent 5px 10px);
  background-color: transparent;
  border: 1px dashed var(--line);
  height: 7px;
}
.meter.is-missing .meter-value { color: var(--ink-4); font-weight: 560; font-size: 12px; }

.meter[data-sub="conversationQuality"] .meter-fill { background: var(--sub-conversation); }
.meter[data-sub="followThrough"] .meter-fill { background: var(--sub-followthrough); }
.meter[data-sub="goalProgress"] .meter-fill { background: var(--sub-goal); }
.meter[data-sub="capabilityGrowth"] .meter-fill { background: var(--sub-capability); }
.meter[data-sub="relationshipHealth"] .meter-fill { background: var(--sub-relationship); }

/* The index score itself. Large, plain, and honest when it cannot be computed. */
.score {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.score-num { font-family: var(--font-num); font-size: 38px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.score-of { color: var(--ink-4); font-size: 14px; }
.score.is-missing .score-num { font-size: 17px; font-weight: 620; color: var(--ink-3); }

.band { display: inline-flex; align-items: center; gap: 6px; font-weight: 640; font-size: 12.5px; }
.band::before { content: ""; width: 8px; height: 8px; border-radius: 3px; background: currentColor; }
.band[data-band="thriving"] { color: var(--good); }
.band[data-band="onTrack"] { color: var(--brand); }
.band[data-band="uneven"] { color: var(--warn); }
.band[data-band="slipping"] { color: var(--accent); }
.band[data-band="stalled"] { color: var(--bad); }

/* The protocol stage rail. This is the one piece of the interface that is
   unusual, and it earns its place: it is the only way to see, live, that the
   conversation is actually progressing through the method rather than circling. */
.stages { display: flex; align-items: stretch; gap: 3px; margin: 0; padding: 0; list-style: none; }
.stage {
  flex: 1;
  min-width: 0;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  background: var(--sunken);
  border: 1px solid transparent;
  transition: background .2s ease, border-color .2s ease;
}
.stage-name { font-size: 12px; font-weight: 640; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stage-hint { font-size: 11px; color: var(--ink-4); display: none; }
.stage.done { background: var(--good-soft); }
.stage.done .stage-name { color: var(--good); }
.stage.current { background: var(--brand-soft); border-color: var(--brand-line); }
.stage.current .stage-name { color: var(--brand-ink); }
.stage.current .stage-hint { display: block; color: var(--brand); }

/* A sparkline of session-over-session movement, drawn as inline SVG. */
.spark { display: block; width: 100%; height: 42px; overflow: visible; }
.spark path.line { fill: none; stroke: var(--brand); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.spark path.area { fill: color-mix(in srgb, var(--brand) 12%, transparent); stroke: none; }
/* The end-of-line marker. Drawn as a zero-length round-capped stroke so it stays
   a circle even though the sparkline box is stretched horizontally. */
.spark line.dot { stroke: var(--brand); stroke-width: 6; stroke-linecap: round; }
.spark circle { fill: var(--surface); stroke: var(--brand); stroke-width: 2; }

/* --------------------------------------------------------------- the session */

.session {
  display: grid;
  grid-template-rows: auto 1fr auto;
  /* One column that may shrink below its content: a long unbreakable line in a
     summary card must not widen the whole screen. */
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  height: calc(100dvh - var(--topbar) - 44px);
}

.transcript {
  overflow-y: auto;
  padding: 4px 2px 8px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  scroll-behavior: smooth;
}

.turn { display: flex; gap: 10px; max-width: 760px; }
.turn.mentee { margin-left: auto; flex-direction: row-reverse; }
.turn-avatar {
  width: 30px; height: 30px; flex: none;
  border-radius: 9px;
  display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand-ink);
  font-size: 12px; font-weight: 700;
  overflow: hidden;
}
.turn.mentee .turn-avatar { background: var(--sunken); color: var(--ink-2); }
.turn-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.turn-body {
  padding: 10px 13px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.turn.mentee .turn-body { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.turn.pending .turn-body { color: var(--ink-3); }

.typing { display: inline-flex; gap: 4px; align-items: center; height: 18px; }
.typing i { width: 5px; height: 5px; border-radius: 50%; background: var(--ink-4); animation: blink 1.2s infinite; }
.typing i:nth-child(2) { animation-delay: .18s; }
.typing i:nth-child(3) { animation-delay: .36s; }
@keyframes blink { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

.composer {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
.composer textarea { border: 0; min-height: 40px; max-height: 160px; padding: 6px 4px; resize: none; }
.composer textarea:focus { outline: none; }

/* The round picture control: used by the persona editor and by a person's own
   profile, so it lives here rather than in either screen's stylesheet. */
/* The crop dialog. The circle is an overlay rather than a clip on the picture,
   so the part being cut away stays visible while it is being positioned. */
.crop { display: grid; justify-items: center; gap: 12px; }
.crop-frame {
  position: relative; width: 264px; height: 264px; overflow: hidden;
  border-radius: 14px; background: var(--ink-1); touch-action: none; cursor: grab;
}
.crop-frame.dragging { cursor: grabbing; }
.crop-frame .crop-img { position: absolute; top: 0; left: 0; transform-origin: 0 0; user-select: none; -webkit-user-drag: none; max-width: none; }
.crop-frame .crop-ring {
  position: absolute; inset: 0; pointer-events: none; border-radius: 14px;
  box-shadow: 0 0 0 999px rgba(0, 0, 0, 0.45) inset;
  -webkit-mask: radial-gradient(circle at 50% 50%, transparent 0 128px, #000 129px);
  mask: radial-gradient(circle at 50% 50%, transparent 0 128px, #000 129px);
}
.crop-controls { display: flex; align-items: center; gap: 10px; width: 100%; max-width: 264px; }
.crop-controls .crop-zoom { flex: 1; }

.persona-face-row { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 14px; }
/* The controls beside the face may shrink: at 320px the two buttons were 24px
   wider than the card and wrap instead. */
.persona-face-row > :not(.persona-face) { flex: 1 1 auto; min-width: 0; }
@media (max-width: 360px) { .persona-face-row { flex-wrap: wrap; } }
.persona-face {
  position: relative; flex: none; width: 76px; height: 76px; border-radius: 50%;
  overflow: hidden; background: var(--sunken); border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
}
.persona-face-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.persona-face-empty { display: flex; color: var(--ink-4); }
.persona-face-empty svg { display: block; }

.me-face {
  width: 22px; height: 22px; border-radius: 50%; overflow: hidden; flex: none;
  display: block; background: var(--sunken);
}
.me-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
.acc-person { display: flex; align-items: center; gap: 8px; }
.team-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: inherit; }

/* One row of the reset queue on the accounts screen: who is locked out, when
   they said so, and the two things that can be done about it. */
.acc-reset-row {
  display: flex; gap: 12px; align-items: center; justify-content: space-between;
  flex-wrap: wrap; padding: 11px 0; border-bottom: 1px solid var(--line-soft);
}
.acc-reset-row:last-child { border-bottom: 0; }

/* ------------------------------------------------------------------- states */

.empty {
  display: grid;
  place-items: center;
  gap: 10px;
  padding: 44px 20px;
  text-align: center;
  color: var(--ink-3);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.empty svg { width: 30px; height: 30px; color: var(--ink-4); }
.empty h3 { color: var(--ink-2); }

.skeleton {
  background: linear-gradient(90deg, var(--sunken) 25%, var(--line-soft) 37%, var(--sunken) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
@keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* Install ribbon (env-badge.js): only the test server draws it. Above the boot
   cover, and click-through so it never sits on top of a button. */
.env-badge {
  position: fixed; top: 0; left: 50%; transform: translateX(-50%); z-index: 1100;
  padding: 3px 14px; border-radius: 0 0 8px 8px;
  background: #E8590C; color: #fff; font: 700 11px/1.4 system-ui, sans-serif; letter-spacing: .12em;
  pointer-events: none; box-shadow: 0 1px 4px rgb(0 0 0 / .18);
}

/* The loading cover (index.html #boot): one ring turning over the page colour
   until the first screen has rendered, then a short fade (app.js hideBoot). */
.boot {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: var(--bg);
  transition: opacity .28s ease, visibility 0s linear .28s;
}
.boot.done { opacity: 0; visibility: hidden; pointer-events: none; }
.boot-ring {
  position: relative;
  width: 46px;
  height: 46px;
  border-radius: 50%;
}
.boot-ring::before,
.boot-ring::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3.5px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3.5px));
}
/* The track, then the turning arc: brand colour fading out along its tail. */
.boot-ring::before { background: var(--line-soft); }
.boot-ring::after {
  background: conic-gradient(from 0deg, transparent 0 18%, color-mix(in oklch, var(--brand) 35%, transparent) 45%, var(--brand) 100%);
  animation: boot-spin .85s linear infinite;
}
.boot-mark { width: 116px; height: auto; opacity: .85; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .boot-mark { content: url("/assets/lockup-light.png"); }
}
:root[data-theme="dark"] .boot-mark { content: url("/assets/lockup-light.png"); }
@keyframes boot-spin { to { transform: rotate(1turn); } }
@media (prefers-reduced-motion: reduce) {
  .boot-ring::after { animation-duration: 2.4s; }
}
.skeleton.line { height: 12px; margin-bottom: 9px; }
.skeleton.card { height: 120px; }

.banner {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 11px 13px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-2);
  margin-bottom: 14px;
}
.banner svg { width: 18px; height: 18px; flex: none; margin-top: 1px; }
.banner.warn { background: var(--warn-soft); border-color: var(--warn); color: var(--warn-ink); }
.banner.bad { background: var(--bad-soft); border-color: var(--bad); color: var(--bad-ink); }
.banner.brand { background: var(--brand-soft); border-color: var(--brand-line); color: var(--brand-ink); }
.banner .spacer { margin-left: auto; }
/* On a phone the action and the sentence were fighting over one line, and the
   sentence lost: it came out as a column six words wide beside a button that
   kept its full width. */
@media (max-width: 560px) {
  /* .hero is a banner too and has its own layout, so it is left alone. */
  .banner:not(.hero) { flex-wrap: wrap; }
  .banner:not(.hero) > span { flex: none; }
  .banner:not(.hero) > div:not(.spacer) { flex: 1 1 0; min-width: 0; }
  /* The action drops to its own line, indented past the icon so it reads as
     belonging to the sentence above it. */
  .banner:not(.hero) .spacer { flex: 1 1 100%; margin: 4px 0 0 28px; }
  .banner:not(.hero) .spacer .btn { width: 100%; }
}

/* -------------------------------------------------------------------- modal */

.modal-back {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 20px;
  background: oklch(14% 0.02 155 / .5);
  backdrop-filter: blur(3px);
}
.modal {
  width: min(680px, 100%);
  max-height: calc(100dvh - 60px);
  overflow-y: auto;
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 20px;
}
.modal.wide { width: min(940px, 100%); }
.modal-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.modal-foot { display: flex; gap: 8px; justify-content: flex-end; margin-top: 18px; }

/* -------------------------------------------------------------------- toast */

.toasts { position: fixed; right: 16px; bottom: 16px; z-index: 80; display: flex; flex-direction: column; gap: 8px; }
.toast {
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--ink);
  color: var(--surface);
  box-shadow: var(--shadow-lg);
  font-size: 13.5px;
  max-width: 340px;
  animation: rise .18s ease;
}
.toast.bad { background: var(--bad); }
.toast.good { background: var(--good); }
@keyframes rise { from { transform: translateY(6px); opacity: 0; } }

/* ------------------------------------------------------------------- dials */

.dial { margin-bottom: 16px; }
.dial-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
.dial-head label { font-weight: 600; font-size: 13px; }
.dial-head .val { margin-left: auto; font-size: 12.5px; color: var(--brand); font-weight: 640; }
.dial input[type="range"] { width: 100%; accent-color: var(--brand); }
.dial .desc {
  margin-top: 5px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  color: var(--brand-ink);
  font-size: 12.5px;
}

/* ------------------------------------------------------------------ segment */

.segment { display: inline-flex; padding: 3px; border-radius: 10px; background: var(--sunken); gap: 2px; }
.segment button {
  border: 0; background: none; font: inherit; font-size: 12.5px; font-weight: 580;
  padding: 5px 11px; border-radius: 8px; cursor: pointer; color: var(--ink-3);
}
.segment button.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); }

/* ------------------------------------------------------------------ mobile */

@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  .rail {
    position: fixed;
    inset: 0 auto 0 0;
    width: 260px;
    z-index: 50;
    transform: translateX(-100%);
    transition: transform .2s ease;
    box-shadow: var(--shadow-lg);
  }
  body.rail-open .rail { transform: none; }
  body.rail-open::after {
    content: "";
    position: fixed; inset: 0; z-index: 40;
    background: oklch(14% 0.02 155 / .45);
  }
  .page { padding: 16px 14px 56px; }
  .topbar { padding: 0 14px; }
  .stages { flex-wrap: wrap; }
  .stage { flex: 1 1 100px; }
  .turn { max-width: 100%; }
  .session { height: auto; min-height: calc(100dvh - var(--topbar) - 32px); }
}

@media (min-width: 901px) { .only-mobile { display: none !important; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  .transcript { scroll-behavior: auto; }
}

/* ------------------------------------------------------- rhythm on a screen
   Added after the first pass over the screens. The complaint was not that any
   one card was wrong, it was that twelve of them in a column read as a wall.
   These give a screen a few landmarks and let a number be a number rather than
   a row in a list. Nothing above this line changed. */

/* A short heading over a group of cards. */
.section { margin-top: 26px; }
.section:first-child { margin-top: 0; }
.section-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 0 2px 11px; }
.section-head h2 { font-size: 15px; }
.section-head .note { color: var(--ink-3); font-size: 12.5px; }
.section-head .spacer { margin-left: auto; }

/* Stat tiles. The same four numbers as a definition list read as a form; on
   tiles they read as a summary you can take in without reading. */
.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 10px; }
.stat {
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 11px 13px;
}
.stat b { display: block; font-family: var(--font-num); font-variant-numeric: tabular-nums; font-size: 19px; font-weight: 700; line-height: 1.25; }
.stat span { display: block; font-size: 12px; color: var(--ink-3); }
.stat.is-accent { background: var(--accent-soft); border-color: var(--accent-line); }
.stat.is-accent b { color: var(--accent-ink); }
.stat.is-quiet b { font-size: 13.5px; font-weight: 600; }

/* A row of people is not a spreadsheet. */
.table.roomy th { padding: 0 12px 10px; }
.table.roomy td { padding: 15px 12px; }

/* The ring, and the sentences that say what it does and does not mean. */
.donut-row { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.donut-row .donut-copy { flex: 1 1 220px; min-width: 0; }
.donut-row .donut-copy p { margin-bottom: 6px; }

/* A stepper showing a method nobody has walked yet: no stage is done and none
   is locked, it is simply the shape of a session. */
.stepper.is-preview .step-node { background: var(--brand-soft); color: var(--brand-ink); box-shadow: 0 0 0 1px var(--brand-line); }
.stepper.is-preview .step::before { background: var(--brand-line); }
.stepper.is-preview .step-label { color: var(--ink); }

/* An empty state somebody will sit in front of for more than a moment. Small
   inline empties keep the icon; a picture on every empty list is worse than
   none. */
.empty.has-photo { padding: 34px 20px 38px; }
.empty-photo {
  width: min(248px, 68%);
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius-lg);
  margin-bottom: 2px;
}
@media (max-width: 480px) { .empty-photo { width: min(196px, 74%); } }

/* A long name in the top bar pushed the whole page sideways at 390px, which
   showed up the moment a screen was opened from an account whose name is longer
   than the test administrator's. The bar is shell, not a screen, so it is
   constrained here rather than rebuilt. */
@media (max-width: 900px) {
  .topbar > div { min-width: 0; }
  .topbar .crumb, .topbar .crumb-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .topbar-actions { min-width: 0; }
  .topbar-actions .segment { flex: none; }
  .topbar-actions #meButton { min-width: 0; flex: 0 1 auto; max-width: 28vw; }
  .topbar-actions #meButton span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  /* The squeeze has to land on the BREADCRUMB, which is the one thing here that
     can lose a word and still be understood.
     `.btn.icon` sets width: 36px, which in a flex row is a starting size and not
     a floor, so with min-width relaxed above the buttons were what gave way
     instead: measured at 390px the appearance toggle came out 18px wide and the
     menu button 24px, half a thumb on the one width where a thumb is the only
     thing available. Pinning them alone then pushed the bar 15px past the edge
     at 320px in Thai, because the breadcrumb was shrinking proportionally and
     stopping at 97px rather than absorbing what was left - `flex: 1 1 0` is what
     makes it claim no intrinsic width and take the whole shortfall. Both halves
     are needed; either on its own trades one fault for the other. */
  .topbar > div:not(.topbar-actions) { flex: 1 1 0; }
  .topbar .btn.icon { flex: none; }
}

/* A button on the band is a button, not a link with a rule under it. */
.hero a.btn, .hero a.btn:hover { text-decoration: none; }

/* The manager's band.
   The supplied banner artwork carries the campaign line and belongs to the
   mentee's welcome screen. On a working board about named people it is the
   wrong register, and an administrator sees both screens, so it would be the
   same photograph twice in one session. Team gets its own picture in the same
   shape as the house band: the person on the right, the copy on solid brand
   green on the left, and no seam where one becomes the other. --band stays dark
   in both themes, exactly as .hero.banner does. */
.hero.team-band {
  padding: 0;
  background: var(--band);
  min-height: 250px;
  display: flex;
  align-items: center;
}
.hero.team-band::after { display: none; }
.hero.team-band .hero-body {
  position: relative;
  z-index: 1;
  width: min(45%, 480px);
  padding: 26px 0 26px 30px;
}
.team-band-photo { position: absolute; inset: 0 0 0 auto; width: 62%; }
.team-band-photo img { width: 100%; height: 100%; object-fit: cover; object-position: 54% 24%; }
.team-band-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--band) 0%, color-mix(in srgb, var(--band) 76%, transparent) 28%, transparent 64%);
}
@media (max-width: 860px) {
  /* Same reasoning as the banner: the diagonal cannot do its job this narrow,
     so the picture goes on top and the copy sits on the panel blue below. */
  .hero.team-band { display: block; min-height: 0; }
  .team-band-photo { position: relative; width: auto; height: 180px; }
  .team-band-photo img { object-position: 54% 10%; }
  .team-band-photo::after {
    background: linear-gradient(180deg, transparent 32%, color-mix(in srgb, var(--band) 68%, transparent) 76%, var(--band) 100%);
  }
  .hero.team-band .hero-body { width: auto; padding: 16px 22px 24px; }
}

/* Five sub-score bars across a full-width card are five very long thin lines
   with a number stranded at the far end. In two columns they read as a group
   and the eye can pair the label with its value. */
.subs-2 > div { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 0 30px; }

/* =====================================================================
   AUVOX 2.0 polish layer (Pimma, 2026-10-06)
   Shared classes so every screen - including ones added later (practice
   bots, share links, roles) - inherits the AUVOX look by using them:
     .bot-kind-badge[data-kind=practice|mentor]   kind pill above a bot's name
     [data-kind=practice|mentor] on a bot card     kind accent edge + tint
     .bot-art[data-kind=practice|mentor|empty]     spot illustration (themed)
     .surface-card / .eyebrow / .live-dot          AUVOX card, label, live signal
   Text on a solid --brand fill is var(--on-brand), never #fff.
   ===================================================================== */

/* -- kind of bot ---------------------------------------------------- */
.bot-kind-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  width: max-content;
  max-width: 100%;
  margin: 0 0 4px;
  padding: 2px 9px 2px 7px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  line-height: 1.6;
  background: var(--kind-mentor-soft);
  color: var(--kind-mentor-ink);
  border: 1px solid color-mix(in srgb, var(--kind-mentor) 40%, transparent);
}
.bot-kind-badge svg { width: 12px; height: 12px; flex: none; display: block; }
.bot-kind-badge > span { display: inline-flex; }
.bot-kind-badge[data-kind="practice"] {
  background: var(--kind-practice-soft);
  color: var(--kind-practice-ink);
  border-color: color-mix(in srgb, var(--kind-practice) 40%, transparent);
}
/* The card's edge says the kind, whatever accent colour a persona was given -
   the old per-persona accents were HomePro blue/orange, and they arrive as an
   inline --personas-accent, so the kind colour is set on its own property. */
[data-kind="practice"] { --kind-colour: var(--kind-practice); }
[data-kind="mentor"] { --kind-colour: var(--kind-mentor); }
.personas-card[data-kind] .personas-edge { background: var(--kind-colour); }
[data-kind].card {
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--kind-colour) 7%, transparent), transparent 110px),
    var(--surface);
}
.personas-name { min-width: 0; }
.personas-card[data-kind] .persona-face { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px color-mix(in srgb, var(--kind-colour) 60%, transparent); }

/* spot illustrations, one cut per theme */
.bot-art {
  display: block;
  width: 120px;
  aspect-ratio: 1 / 1;
  background: center / contain no-repeat url("/assets/art/empty-state.webp");
}
.bot-art[data-kind="practice"] { background-image: url("/assets/art/bot-practice.webp"); }
.bot-art[data-kind="mentor"] { background-image: url("/assets/art/bot-mentor.webp"); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .bot-art { background-image: url("/assets/art/empty-state-dark.webp"); }
  :root:not([data-theme="light"]) .bot-art[data-kind="practice"] { background-image: url("/assets/art/bot-practice-dark.webp"); }
  :root:not([data-theme="light"]) .bot-art[data-kind="mentor"] { background-image: url("/assets/art/bot-mentor-dark.webp"); }
}
:root[data-theme="dark"] .bot-art { background-image: url("/assets/art/empty-state-dark.webp"); }
:root[data-theme="dark"] .bot-art[data-kind="practice"] { background-image: url("/assets/art/bot-practice-dark.webp"); }
:root[data-theme="dark"] .bot-art[data-kind="mentor"] { background-image: url("/assets/art/bot-mentor-dark.webp"); }

/* -- small AUVOX primitives ---------------------------------------- */
.eyebrow {
  display: block;
  margin: 0 0 6px;
  color: var(--brand);
  font-family: var(--font-display);
  font-size: 11.5px;
  font-weight: 650;
  letter-spacing: .09em;
  text-transform: uppercase;
}
.live-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--live);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--live) 25%, transparent);
  flex: none;
}
.surface-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 22px 24px;
}

/* -- empty states --------------------------------------------------- */
/* The icon sits in a soft green medallion rather than floating grey, and the
   card is a quiet tinted panel instead of a dashed box. */
.empty {
  border: 1px solid var(--line-soft);
  background:
    radial-gradient(90% 70% at 50% 0%, color-mix(in srgb, var(--brand) 6%, transparent), transparent 70%),
    var(--surface);
  padding: 40px 22px;
  gap: 12px;
}
.empty > div:first-child:has(> svg) {
  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: var(--brand-soft);
  box-shadow: inset 0 0 0 1px var(--brand-line);
}
.empty > div:first-child > svg { width: 26px; height: 26px; color: var(--brand); }
.empty h3 { color: var(--ink); font-size: 16px; }
.empty p { max-width: 60ch; margin: 0 auto; line-height: 1.6; }
/* .empty svg above is for the medallion; a button inside an empty state keeps
   its own 16px icon (the home "Talk to a mentor" icon came out 30px). */
.empty .btn svg { width: 16px; height: 16px; color: currentColor; }
.empty .btn { margin-top: 4px; }

/* -- cards and rhythm ----------------------------------------------- */
.card { border-color: var(--line-soft); }
.page-head h1 { font-size: 26px; }
.page-head .lede { line-height: 1.6; }
.section-head h2 { font-family: var(--font-display); }
.rail-group { color: var(--ink-3); font-weight: 650; }
.rail .brand-sub { color: var(--ink-3); letter-spacing: .03em; }
.nav-link .pip { font-family: var(--font-num); }
.segment button.active { color: var(--brand-ink); }
.tag { font-weight: 620; }

/* -- colours that screens write into their own <style>/style="" ---- */
/* Each of these is a light-theme ink pinned in a screen module; in the dark
   theme it landed dark-on-dark. Re-pointed to tokens here (one class more
   specific via :root) so the screens need no edit. */
:root .programs-step.done b,
:root .programs-step.current,
:root .programs-rung.is-expected .programs-rung-tag { color: var(--on-brand); }
:root .programs-step.current b { background: color-mix(in srgb, var(--on-brand) 20%, transparent); color: var(--on-brand); }
:root .person-fact.is-accent b,
:root .team-stat.is-accent b,
:root .team-need-mark,
:root .org-consequence.on { color: var(--accent-ink); }
:root .conv-mark { background: var(--accent-soft); color: var(--accent-ink); }
[style*="#8A4A0C"] { color: var(--accent-ink) !important; }

/* -- touch: 44px targets on phones ------------------------------------ */
@media (max-width: 900px), (pointer: coarse) {
  .btn { min-height: 44px; }
  .btn.sm { min-height: 40px; }
  .btn.icon { width: 44px; }
  .btn.icon.sm { width: 40px; }
  .nav-link { min-height: 44px; }
  .nav-twist { width: 44px; }
  .segment button { min-height: 36px; padding: 6px 12px; }
  input[type="text"], input[type="email"], input[type="password"], input[type="number"],
  input[type="date"], input[type="search"], select { min-height: 44px; }
}
/* iOS zooms into any field under 16px; stop that on touch devices only. */
@media (pointer: coarse) {
  input[type="text"], input[type="email"], input[type="password"], input[type="number"],
  input[type="date"], input[type="search"], select, textarea { font-size: 16px; }
}

/* -- the top bar on a phone (AUVOX 2.0 wave 3) -------------------------
   At 390px the page title was squeezed to "AI…" by the account name. On a
   phone the account button is the avatar alone (the name is in the profile
   dialog it opens), and the title may take two lines instead of an ellipsis. */
@media (max-width: 600px) {
  .topbar { gap: 8px; }
  .topbar-actions { gap: 6px; }
  .topbar-actions #meButton { width: 44px; padding: 0; justify-content: center; flex: none; }
  .topbar-actions #meButton span:last-child { display: none; }
  .topbar .crumb {
    white-space: normal; overflow-wrap: anywhere; line-height: 1.25; font-size: 14.5px;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  }
  .topbar .crumb-sub { font-size: 12px; }
}
@media (max-width: 360px) {
  .topbar-actions .segment button { padding: 6px 8px; }
  .topbar { padding: 0 10px; }
}

/* bot list filter (personas.js) and home bot cards: a hidden card is gone */
.personas-filter { margin: 0 0 14px; flex-wrap: wrap; }
.personas-card[hidden], .home-bot[hidden] { display: none !important; }
.timing-scroll { overflow-x: auto; margin-bottom: 12px; }
