/*
 * Design system — TutorTalks Design Language 2026.
 *
 * Shared by every page. The tokens below are the kit's (design/kit/tokens.css, the
 * same file the Figma foundations were generated from — keep them in sync by copying,
 * never by editing here): semantic colour roles for light and dark, the two faces
 * (Lora for the thing you read first, Inter for everything operational), named text
 * styles, the 4px space scale, radii (0 / 2 / 3), rules, the one overlay shadow, sizes
 * and the 1440 layout grid. Page sheets layer on top and never redefine a token; the
 * component kit lives in components.css (.tt-* classes). Measured contrast for every
 * pair: design/system/CONTRAST.md. Brand rules: docs/BRAND.md.
 *
 * LEGACY ALIASES. The second block maps the previous token names (--accent, --bg,
 * --text-dim, --s-*, --t-*, --r-* …) onto the new roles so every page not yet
 * re-templated onto the kit renders in the new language immediately. They are
 * aliases, not values: delete them page by page as the old class vocabulary goes.
 */

/* TutorTalks Design Language 2026 — tokens
   Every value the kit and the screens use, as custom properties on :root (light, the default)
   with the dark-mode values under [data-theme="dark"]. Names are semantic and stable: screens
   use the role (--color-live-text, --color-field-reading), never the hue (teal, cream); the hues
   live only under --brand-*. Measured contrast: system/CONTRAST.md (tools/contrast.mjs). */

:root {
  color-scheme: light;

  /* ---------- colour · brand hues (reference only; screens use the roles below) ---------- */
  --brand-navy: #15203A;
  --brand-cream: #F6F2EA;
  --brand-slate: #C9CFDB;
  --brand-teal: #00A9BE;
  --brand-deep-teal: #0B7A8A;
  --brand-orange: #E2733A;

  /* ---------- colour · grounds and fields ---------- */
  --color-ground: #FFFFFF;            /* the working surface: editor, lists, tables, forms, dialogs */
  --color-input: #FFFFFF;             /* the fill of a text field, select, chip, secondary button */
  --color-field-reading: #F6F2EA;     /* bounded reading field (cream in light, a deep navy in dark): context column, transcripts, insights, marketing bands */
  --color-field-navy: #15203A;        /* dark field, navy in both themes: masthead, key-figure band, student stage, join band */
  --color-surface-raised: #22304F;    /* raised surface on navy: readout cells, selected segment, monogram, the composer and chips on the stage */
  --color-field-live: #00A9BE;        /* teal field, teal in both themes: only where the live conversation is (Live now, the student door) */

  /* ---------- colour · ink on light grounds (white and the reading field) ---------- */
  --color-ink: #15203A;               /* text, titles, rules, chart marks */
  --color-ink-2: #4A5468;             /* secondary text, column headers, hints */
  --color-ink-3: #5F6880;             /* tertiary text, placeholders, timestamps, axis labels, disabled button labels */
  --color-ink-muted: #8A91A3;         /* disabled inputs, chips, tabs and menu items only */

  /* ---------- colour · ink on navy ---------- */
  --color-ink-on-navy: #F6F2EA;
  --color-ink-2-on-navy: #C9CFDB;
  --color-ink-3-on-navy: #A9B1C3;
  --color-ink-muted-on-navy: #6F7A94;
  --color-ink-on-bright: #15203A;     /* the navy label on a bright fill inside a navy context: the teal primary, a cream segment, the salmon confirm */

  /* ---------- colour · ink on the teal field (navy in both themes; the field never flips) ---------- */
  --color-ink-on-live: #15203A;
  --color-ink-3-on-live: #123241;
  --color-rule-on-live: rgba(21, 32, 58, 0.35);     /* rules and the display readout cell's edge on teal */
  --color-cell-on-live: rgba(21, 32, 58, 0.12);     /* readout cell fill on teal */
  --color-hover-on-live: rgba(21, 32, 58, 0.08);
  --color-selected-on-live: rgba(21, 32, 58, 0.10);

  /* ---------- colour · rules and boundaries ---------- */
  --color-rule: rgba(21, 32, 58, 0.14);        /* hairline between rows / kicker rule on light */
  --color-rule-on-navy: rgba(201, 207, 219, 0.22);
  --color-edge: #7A8294;                       /* control boundary on light (≥3:1 on white and the reading field) */
  --color-edge-strong: #15203A;                /* strong boundary, table header rule, section rule, overlay border */
  --color-edge-on-navy: #8C95AA;               /* control boundary on navy: secondary buttons, inputs, chips, input cells */
  --color-meter-track: #DCE0E8;                /* meter and micro-bar track; the disabled primary's fill */
  --color-chart-tint: #DCE0E8;                 /* context bars behind the highlighted series */

  /* ---------- colour · actions ---------- */
  --color-primary: #15203A;                    /* primary button on light: navy fill */
  --color-primary-label: #F6F2EA;              /* cream label */
  --color-primary-hover: #2A3756;
  --color-primary-active: #0F1729;
  --color-primary-fixed: #15203A;              /* the navy primary on fields that do not change with the theme: the teal door, the briefing card */
  --color-primary-fixed-label: #F6F2EA;
  --color-primary-fixed-hover: #2A3756;
  --color-primary-fixed-active: #0F1729;
  --color-live: #00A9BE;                       /* teal: live fields, primary on navy, pips on navy */
  --color-live-hover: #1FB9CC;
  --color-live-active: #0597AA;
  --color-live-text: #0B7A8A;                  /* deep teal: Live, Online now, the student's speaker label, pips on light */
  --color-link: #15203A;                       /* links are navy, underlined */
  --color-link-hover: #0B7A8A;
  --color-focus: #0B7A8A;                      /* focus ring on light */
  --color-focus-on-navy: #00A9BE;
  --color-hover: rgba(21, 32, 58, 0.04);       /* hovered row / quiet button; the selected chip's wash (with a navy edge) */
  --color-selected: rgba(11, 122, 138, 0.07);  /* selected row / rail item wash (plus the 2px deep-teal leading rule) */
  --color-hover-on-navy: rgba(246, 242, 234, 0.07);
  --color-selected-on-navy: rgba(0, 169, 190, 0.16);
  --color-scrim: rgba(21, 32, 58, 0.40);
  --color-kbd-edge-on-primary: rgba(246, 242, 234, 0.45); /* keycap edge inside the navy primary and the tooltip */
  --color-kbd-edge-on-live: rgba(21, 32, 58, 0.45);       /* keycap edge inside the teal primary */

  /* ---------- colour · attention and status ---------- */
  --color-attention: #E2733A;                  /* the spark; at most one 8px attention square per screen, never text, never in the rail */
  --color-danger: #B42318;                     /* red family: Could not save, REC, End, timer at 20 s or less */
  --color-danger-hover: #981C12;
  --color-danger-label: #FFFFFF;               /* label on the solid danger confirm (navy in dark, where danger is salmon) */
  --color-danger-on-navy: #F28B82;
  --color-danger-hover-on-navy: #F6A49D;
  --color-danger-tint: #FBECEA;
  --color-danger-tint-on-navy: rgba(242, 139, 130, 0.14);
  --color-warning: #8A5A00;                    /* amber family: Unsaved changes, timer at 60 s or less, blocked line, room paused */
  --color-warning-on-navy: #F0B35C;
  --color-warning-tint: #FBF0DA;
  --color-warning-tint-on-navy: rgba(240, 179, 92, 0.14);
  --color-success: #1B7038;                    /* green family: All changes saved, Session created, Ready */
  --color-success-on-navy: #7BD389;
  --color-success-tint: #E6F3EA;
  --color-success-tint-on-navy: rgba(123, 211, 137, 0.14);
  --color-info: #15203A;                       /* info is navy / slate, never teal (teal means live); Thinking… on the stage */
  --color-info-on-navy: #C9CFDB;
  --color-info-tint: #E9ECF2;
  --color-info-tint-on-navy: rgba(201, 207, 219, 0.12);
  /* status on the teal field (fixed in both themes): the darkest member of each family, measured as text and as a control edge on
     #00A9BE. Anything that passes 4.5:1 on teal is nearly black, so the glyph and the word carry the meaning; info is navy, as everywhere. */
  --color-danger-on-live: #52080C;                 /* 5.30:1 — the door's error cells and inline error, the outlined End on Live now */
  --color-danger-hover-on-live: #3E050A;           /* 6.03:1 — the pressed edge and label (5.19:1 on the tint) */
  --color-danger-tint-on-live: rgba(82, 8, 12, 0.08); /* the hovered / pressed wash of an outlined danger button on teal (danger on it 4.57:1) */
  --color-warning-on-live: #3C2800;                /* 4.96:1 */
  --color-success-on-live: #0A3318;                /* 4.95:1 */
  --color-info-on-live: #15203A;                   /* 5.71:1 — navy, never teal */

  /* ---------- colour · overlays and the stage ---------- */
  --color-tooltip: #15203A;                    /* tooltip plate, navy in both themes */
  --color-tooltip-ink: #F6F2EA;
  --color-tooltip-edge: #8C95AA;               /* 1px edge so the plate keeps its boundary on a dark ground */
  --color-captions-scrim: rgba(21, 32, 58, 0.84); /* captions over the video */
  --color-mic-halo: rgba(0, 169, 190, 0.35);   /* the held mic's 4px halo (decorative; the mic itself is the boundary) */
  --color-mic-level-track: rgba(21, 32, 58, 0.25);

  /* ---------- colour · the briefing card (a cream reading field on the navy stage; fixed in both themes) ---------- */
  --color-briefing-field: #F6F2EA;
  --color-briefing-ink: #15203A;
  --color-briefing-ink-2: #4A5468;
  --color-briefing-ink-3: #5F6880;
  --color-briefing-rule: rgba(21, 32, 58, 0.14);
  --color-briefing-warning: #8A5A00;
  --color-briefing-danger: #B42318;            /* the Recorded fact's dot on the card (5.89:1 on the briefing field) */
  --color-briefing-focus: #0B7A8A;
  --color-briefing-track: #DCE0E8;
  --color-briefing-hover: rgba(21, 32, 58, 0.04);
  --color-briefing-selected: rgba(11, 122, 138, 0.07);
  --color-kbd-edge-on-primary-fixed: rgba(246, 242, 234, 0.45); /* keycap edge on the fixed navy primary */

  /* ---------- colour · charts ---------- */
  --color-chart-1: #15203A;                    /* all series but one */
  --color-chart-2: #0B7A8A;                    /* the one highlighted series: student speaking time */
  --color-chart-grid: rgba(21, 32, 58, 0.14);
  --color-chart-1-on-navy: #C9CFDB;
  --color-chart-2-on-navy: #00A9BE;

  /* ---------- type · families ---------- */
  --font-serif: "Lora", Georgia, serif;
  --font-sans: "Inter", system-ui, sans-serif;

  /* ---------- type · named styles (font shorthand + tracking); one Figma text style each ---------- */
  --text-display-xl: 500 88px/1.02 var(--font-serif);   --tracking-display-xl: -0.02em;   /* master line (56–88) */
  --text-display-lg: 500 64px/1.04 var(--font-serif);   --tracking-display-lg: -0.02em;   /* one statement per band */
  --text-display-md: 500 48px/1.08 var(--font-serif);   --tracking-display-md: -0.018em;  /* marketing section titles */
  --text-title-xl: 600 40px/44px var(--font-serif);     --tracking-title-xl: -0.015em;    /* door titles, large page titles */
  --text-title-lg: 600 28px/32px var(--font-serif);     --tracking-title-lg: -0.012em;    /* app page title */
  --text-title-md: 600 21px/26px var(--font-serif);     --tracking-title-md: -0.01em;     /* section and dialog titles */
  --text-title-sm: 600 17px/22px var(--font-serif);     --tracking-title-sm: -0.005em;    /* row heads, live session titles */
  --text-attention: 500 17px/24px var(--font-serif);    --tracking-attention: -0.005em;   /* the Needs-attention sentence */
  --text-figure-xl: 500 96px/88px var(--font-serif);    --tracking-figure-xl: -0.035em;   /* the one displayed figure (72–100) */
  --text-figure-lg: 500 36px/40px var(--font-serif);    --tracking-figure-lg: -0.015em;   /* key figures */
  --text-figure-md: 500 28px/32px var(--font-serif);    --tracking-figure-md: -0.012em;   /* module figures */
  --text-figure-unit: 500 32px/40px var(--font-sans);   --tracking-figure-unit: -0.01em;  /* units beside figure-xl */
  --text-note-numeral: 600 12px/16px var(--font-serif); --tracking-note-numeral: 0;       /* the numbered notes on a chart */
  --text-quote-lg: 400 20px/30px var(--font-serif);     --tracking-quote-lg: 0;           /* quoted lines, marketing (italic allowed) */
  --text-quote: 400 16px/24px var(--font-serif);        --tracking-quote: 0;              /* quoted student / avatar lines (italic allowed) */
  --text-reading: 400 16px/23px var(--font-serif);      --tracking-reading: 0;            /* conversation lines: stage and transcript */
  --text-caption: 400 17px/25px var(--font-serif);      --tracking-caption: 0;            /* captions over the video */
  --text-code: 600 32px/36px var(--font-sans);          --tracking-code: 0.12em;          /* join code readout, grouped 3+3, tabular */
  --text-code-lg: 600 40px/48px var(--font-sans);       --tracking-code-lg: 0.12em;       /* projection cells 48×64 */
  --text-code-sm: 600 18px/24px var(--font-sans);       --tracking-code-sm: 0.12em;       /* 26×32 cells inside a table only */
  --text-code-inline: 600 15px/20px var(--font-sans);   --tracking-code-inline: 0.12em;   /* a code inside a sentence */
  --text-lead: 400 18px/28px var(--font-sans);          --tracking-lead: -0.004em;        /* marketing intro paragraphs */
  --text-body-lg: 400 16px/26px var(--font-sans);       --tracking-body-lg: -0.003em;     /* marketing body; phone and stage inputs */
  --text-body: 400 14px/20px var(--font-sans);          --tracking-body: 0;               /* UI sentences */
  --text-body-sm: 400 13px/18px var(--font-sans);       --tracking-body-sm: 0;            /* tables, hints, meta, glosses */
  --text-ui: 500 14px/20px var(--font-sans);            --tracking-ui: 0;                 /* navigation, controls, figure units, suggestion phrases */
  --text-button: 600 14px/20px var(--font-sans);        --tracking-button: 0;             /* 36px buttons; banner and insight titles; the countdown */
  --text-button-lg: 600 15px/20px var(--font-sans);     --tracking-button-lg: 0;          /* 44px buttons (phone, the stage composer) */
  --text-button-sm: 600 13px/16px var(--font-sans);     --tracking-button-sm: 0;          /* 32px buttons, action links, the person's name */
  --text-kicker: 600 13px/18px var(--font-sans);        --tracking-kicker: 0;             /* sentence-case ruled kicker; status words; figure labels; speakers */
  --text-label: 600 12px/16px var(--font-sans);         --tracking-label: 0.01em;         /* field labels, column headers */
  --text-label-caps: 600 12px/16px var(--font-sans);    --tracking-label-caps: 0.06em;    /* uppercase, ≤3 words only */
  --text-micro: 500 12px/16px var(--font-sans);         --tracking-micro: 0;              /* axis labels, counters, keycaps, badges — the floor */
  --text-note: 400 12px/16px var(--font-sans);          --tracking-note: 0;               /* the floor at 400: units under a header, secondary table lines, notes, captions, timestamps, the tooltip */
  --text-ui-sm: 500 13px/18px var(--font-sans);         --tracking-ui-sm: 0;              /* segmented-control items, tabs, the save chip, the phone navigation strip */
  --text-body-lg-strong: 600 16px/26px var(--font-sans); --tracking-body-lg-strong: -0.003em; /* a 600 run inside body-lg (a <b> in marketing or policy body) */
  --text-attention-strong: 600 17px/24px var(--font-serif); --tracking-attention-strong: -0.005em; /* the numbers inside an attention sentence */
  --text-logo: 700 22px/22px var(--font-serif);         --tracking-logo: -0.015em;        /* the wordmark's live letters at the masthead size (kit/logo.html); the only 700 in the system */
  --text-logo-28: 700 28px/28px var(--font-serif);      --tracking-logo-28: -0.015em;
  --text-logo-36: 700 36px/36px var(--font-serif);      --tracking-logo-36: -0.015em;     /* the sign-in door and marketing foot */
  --text-logo-64: 700 64px/64px var(--font-serif);      --tracking-logo-64: -0.015em;     /* the sheet's large specimen */

  /* ---------- space ---------- */
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px; --space-5: 24px;
  --space-6: 32px; --space-7: 48px; --space-8: 64px; --space-9: 96px;

  /* ---------- radius ---------- */
  --radius-0: 0;          /* fields, tables, images, panels */
  --radius-control: 2px;  /* buttons, inputs, chips, segments, monograms */
  --radius-overlay: 3px;  /* dialog, popover, dropdown, toast, tooltip */

  /* ---------- rules ---------- */
  --rule-hair: 1px solid var(--color-rule);
  --rule-strong: 1px solid var(--color-edge-strong);
  --rule-heavy: 2px solid var(--color-edge-strong);
  --rule-on-navy: 1px solid var(--color-rule-on-navy);
  --rule-select: 2px solid var(--color-live-text);   /* leading edge of a selected row / rail item */
  --rule-current: 3px solid var(--color-live);       /* current page bar in the navy masthead */

  /* ---------- shadow (true overlays only) ---------- */
  --shadow-overlay: 0 1px 0 rgba(21, 32, 58, 0.08), 0 12px 32px rgba(21, 32, 58, 0.16);

  /* ---------- sizes ---------- */
  --size-control: 36px;          /* default button, field, select */
  --size-control-compact: 32px;  /* in-row buttons, segmented controls, tabs, chips */
  --size-control-phone: 44px;    /* every target on a phone; the stage composer */
  --size-masthead: 56px;
  --size-monogram: 28px;
  --size-pip: 8px;
  --size-mark: 8px;
  --size-icon: 16px;
  --size-icon-lg: 20px;
  --size-mic: 44px;
  --size-mic-docked: 68px;
  --size-slider-thumb: 20px;

  /* ---------- layout ---------- */
  --layout-frame: 1440px;
  --layout-gutter: 48px;          /* page gutters at 1440 (24 at 1080, 16 on phone) */
  --layout-column: 90px;          /* 12 columns of 90 with 24 gutters inside 48 margins */
  --layout-column-gap: 24px;
  --layout-context: 320px;        /* the reading-field context column (3 columns) */
  --layout-phone: 390px;
}

/* ---------- dark mode: the Light / Dark / System setting keeps working; the student stage, the teal field and the briefing card are fixed ---------- */
[data-theme="dark"] {
  color-scheme: dark;
  --color-ground: #111A2E;
  --color-input: #1A2440;
  --color-field-reading: #1A2440;
  --color-field-navy: #15203A;
  --color-surface-raised: #26345A;
  --color-field-live: #00A9BE;

  --color-ink: #F6F2EA;
  --color-ink-2: #C9CFDB;
  --color-ink-3: #A9B1C3;
  --color-ink-muted: #6F7A94;
  --color-ink-on-navy: #F6F2EA;
  --color-ink-2-on-navy: #C9CFDB;
  --color-ink-3-on-navy: #A9B1C3;

  --color-rule: rgba(201, 207, 219, 0.22);
  --color-edge: #7A8599;
  --color-edge-strong: #C9CFDB;
  --color-edge-on-navy: #8C95AA;
  --color-meter-track: #26345A;
  --color-chart-tint: #26345A;

  --color-primary: #00A9BE;
  --color-primary-label: #15203A;
  --color-primary-hover: #1FB9CC;
  --color-primary-active: #0597AA;
  --color-live-text: #00A9BE;
  --color-link: #F6F2EA;
  --color-link-hover: #00A9BE;
  --color-focus: #00A9BE;
  --color-hover: rgba(246, 242, 234, 0.06);
  --color-selected: rgba(0, 169, 190, 0.14);
  --color-scrim: rgba(0, 0, 0, 0.55);

  --color-danger: #F28B82;
  --color-danger-hover: #F6A49D;
  --color-danger-label: #15203A;
  --color-danger-tint: rgba(242, 139, 130, 0.14);
  --color-warning: #F0B35C;
  --color-warning-tint: rgba(240, 179, 92, 0.14);
  --color-success: #7BD389;
  --color-success-tint: rgba(123, 211, 137, 0.14);
  --color-info: #C9CFDB;
  --color-info-tint: rgba(201, 207, 219, 0.12);

  --color-chart-1: #C9CFDB;
  --color-chart-2: #00A9BE;
  --color-chart-grid: rgba(201, 207, 219, 0.22);
}

/* -- app tokens (not in the kit) -------------------------------------------
 * The device's safe areas, read by the phone layouts of every stage page. */
:root {
  --safe-t: env(safe-area-inset-top, 0px); --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px); --safe-l: env(safe-area-inset-left, 0px);
}

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

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

html,
body {
  margin: 0;
  height: 100%;
}

/*
 * The `hidden` attribute only sets `display: none` in the UA stylesheet, so any
 * author rule with an explicit `display` silently beats it. Several top-level
 * views here are `display: grid` or `display: flex`, which made `hidden` a no-op
 * and rendered every view at once. This is the standard remedy and has to stay.
 */
[hidden] {
  display: none !important;
}

body {
  background: var(--color-ground);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4,
p {
  margin: 0;
}

h1 {
  font: var(--text-title-lg);
  letter-spacing: var(--tracking-title-lg);
}
h2 {
  font: var(--text-title-md);
  letter-spacing: var(--tracking-title-md);
}
h3 {
  font: var(--text-title-sm);
  letter-spacing: var(--tracking-title-sm);
}

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

code,
kbd,
pre {
  font-family: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.92em;
}

.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;
}

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

/* -- scrollbars ----------------------------------------------------------- */

* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-edge) transparent;
}
*::-webkit-scrollbar {
  width: 9px;
  height: 9px;
}
*::-webkit-scrollbar-thumb {
  background: var(--color-edge);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-track {
  background: transparent;
}

/* -- brand ---------------------------------------------------------------- */

/* -- page bar --------------------------------------------------------------
 * Shared top bar used by every entry page (landing, join, setup). Fixed
 * height and padding keep the brand mark visually identical as a user moves
 * between pages instead of the header jumping in size.
 */

/* -- buttons -------------------------------------------------------------- */

/*
 * The AI Session Designer's button, and the confirm button inside it.
 *
 * A gradient rather than another solid accent because it has to sit beside
 * "New session" -- the primary button -- without either one winning. They are
 * two ways into the same place, and two identical primaries would just be a
 * decision the instructor has to make by reading. This one is the brand's own
 * navy-to-cyan sweep (see docs/BRAND.md), which reads as "this one is the
 * clever one" without shouting over the page.
 */

/* A button that reads as a link: needed wherever an inline word acts on the
   page rather than navigating -- "Forgot password?" on the dashboard, "Sign
   out" in the pricing banner -- because a real <a> with no href is unreachable
   by keyboard. Here rather than in one page's stylesheet so both get it. */
.linkbtn {
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-link);
  font: inherit;
  font-size: 13px;
  font-weight: 550;
  cursor: pointer;
  border-radius: var(--radius-control);
}

.linkbtn:hover:not(:disabled) {
  text-decoration: underline;
}

/* Spent, not broken: "Link sent" once a reset mail has gone out. In the link
   colour it still reads as something to press. */
.linkbtn:disabled {
  color: var(--color-ink-3);
  cursor: default;
}

.linkbtn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-ground), 0 0 0 4px var(--color-focus);
}

.btn__icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  flex: 0 0 auto;
  border-radius: var(--radius-control);
  border: 1px solid var(--color-rule);
  background: var(--color-ground);
  color: var(--color-ink-2);
  cursor: pointer;
  transition: color 0.14s, background 0.14s, border-color 0.14s;
}
.btn__icon:hover:not(:disabled) {
  color: var(--color-ink);
  background: var(--color-hover);
  border-color: var(--color-edge);
}
.btn__icon:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

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

/* A setting that does not apply right now. Dimmed rather than removed: the
   hint beside it explains why, and a control that disappears reads as a
   feature we never built. The label keeps full contrast so the sentence
   explaining itself stays readable. */

input[type='range'] {
  width: 100%;
  accent-color: var(--color-primary);
}

/* -- cards & surfaces ----------------------------------------------------- */

.card__title {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* -- badges --------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.015em;
  white-space: nowrap;
  text-transform: uppercase;
}

.badge--live {
  background: var(--color-success-tint);
  color: var(--color-success);
  border-color: color-mix(in srgb, var(--color-success) 32%, transparent);
}
.badge--draft {
  background: var(--color-warning-tint);
  color: var(--color-warning);
  border-color: color-mix(in srgb, var(--color-warning) 32%, transparent);
}

.badge--bad {
  background: var(--color-danger-tint);
  color: var(--color-danger);
  border-color: color-mix(in srgb, var(--color-danger) 32%, transparent);
}

.badge--dot::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  /* A fill, not text -- it keeps the saturated hue while the label next to it
     uses the darkened `--*-text`, which is why this is not `currentColor`. */
  background: var(--badge-dot, currentColor);
}

.badge--live { --badge-dot: var(--color-success); }
.badge--draft { --badge-dot: var(--color-warning); }

.badge--bad { --badge-dot: var(--color-danger); }

/* -- chips (removable tokens) --------------------------------------------- */

/* -- tabs ----------------------------------------------------------------- */

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

/* -- empty state ---------------------------------------------------------- */

/* -- toasts --------------------------------------------------------------- */

/* Displayed at the bottom right of the screen. */
.toasts {
  position: fixed;
  bottom: var(--space-4);
  right: var(--space-4);
  /* Above the dialog scrim (`.modal`, 300): a toast's Undo must stay pressable
     while a dialog is open, and a press on it must not land on the scrim. */
  z-index: 400;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(400px, calc(100vw - 32px));
  pointer-events: none;
}

/* The toast stack and the kit-dialog overlay live outside any `.tt-root`, so
 * the kit's focus ring (components.css) is restated for what they hold. */
.toasts :focus-visible,
.modal--kit :focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-ground), 0 0 0 4px var(--color-focus);
}

/*
 * The kit's toast (design/kit, `.tt-toast`): the overlay look the dialog and
 * menu share -- white, 1px navy edge, radius 3, the overlay shadow -- with the
 * level carried by the icon's colour and the words, never a coloured bar.
 * Markup from toast() in js/ui.js: the level icon, the text, a Dismiss button.
 */
.toast {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  padding: 12px 8px 12px 14px;
  border: 1px solid var(--color-edge-strong);
  border-radius: var(--radius-overlay);
  background: var(--color-ground);
  color: var(--color-ink);
  font: var(--text-body);
  box-shadow: var(--shadow-overlay);
  pointer-events: auto;
  animation: toast-in 0.2s cubic-bezier(0.2, 0.9, 0.3, 1);
  transition: opacity 0.28s, transform 0.28s;
}

.toast__icon {
  display: flex;
  flex: none;
  margin-top: 10px;
  color: var(--color-info);
}

.toast__icon svg {
  display: block;
}

.toast__text {
  flex: 1;
  min-width: 0;
  padding: 8px 0;
}

.toast__dismiss {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--color-ink);
  cursor: pointer;
}

.toast__dismiss:hover {
  background: var(--color-hover);
}

.toast__dismiss:focus-visible {
  outline: 0;
  box-shadow: 0 0 0 2px var(--color-ground), 0 0 0 4px var(--color-focus);
}

/*
 * An action inside a toast -- Undo for everything reversible, Reopen for a
 * closed brief -- drawn as the kit's quiet compact button, beside Dismiss
 * (design/pages/editor/dialogs.html). Inserted by the page's undo helpers
 * (js/instructor.js undoToast, js/session-designer.js actionToast).
 */
.toast__action {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 6px;
  height: 32px;
  margin-top: 0;
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--color-ink);
  font: var(--text-button-sm);
  letter-spacing: var(--tracking-button-sm);
  white-space: nowrap;
  cursor: pointer;
}

.toast__action:hover {
  background: var(--color-hover);
}

.toast__action:active {
  background: var(--color-selected);
}

.toast__action:focus-visible {
  outline: 0;
  box-shadow: 0 0 0 2px var(--color-ground), 0 0 0 4px var(--color-focus);
}

.toast__action svg {
  display: block;
  flex: none;
}

.toast--warning .toast__icon {
  color: var(--color-warning);
}
.toast--error .toast__icon {
  color: var(--color-danger);
}
.toast--success .toast__icon {
  color: var(--color-success);
}

.toast--out {
  opacity: 0;
  transform: translateX(14px);
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateX(18px);
  }
}

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

.modal {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  padding: var(--space-4);
  background: var(--color-scrim);
  backdrop-filter: blur(8px) saturate(1.2);
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  animation: fade-in 0.18s ease;
}

.modal__panel {
  width: min(640px, 100%);
  max-height: min(84vh, 760px);
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-overlay);
  border: 1px solid color-mix(in srgb, var(--color-rule) 70%, transparent);
  background: color-mix(in srgb, var(--color-ground) 96%, transparent);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  box-shadow:
    0 4px 16px rgba(15, 23, 42, 0.08),
    0 16px 48px rgba(15, 23, 42, 0.1);
  animation: modal-in 0.25s cubic-bezier(0.16, 1, 0.3, 1);
  overflow: hidden;
}

.modal__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 20px var(--space-5);
  border-bottom: 1px solid var(--color-rule);
  background: color-mix(in srgb, var(--color-field-reading) 40%, transparent);
}

.modal__body {
  padding: var(--space-5);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/*
 * A modal overlay holding the kit's dialog (`.tt-dialog`, components.css):
 * the plain scrim with no blur, the dialog near the top so it sits inside a
 * 900px viewport; on a phone it docks at the foot as a sheet with stacked
 * 44px buttons (the DOM keeps Cancel first; the foot reverses it so the
 * primary or destructive button is drawn on top). Used by confirmDialog() in
 * js/ui.js and the kit dialogs in js/instructor.js.
 */
.modal.modal--kit {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 136px 16px 24px;
  background: var(--color-scrim);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  overflow-y: auto;
}

.modal--kit .tt-dialog {
  max-width: 100%;
  max-height: calc(100dvh - 160px);
}

.modal--kit .tt-dialog__body {
  overflow-y: auto;
}

.modal--kit .tt-dialog__body p {
  margin: 0;
  color: var(--color-ink);
}

[data-layout='mobile'] .modal.modal--kit {
  align-items: flex-end;
  padding: 0;
}

[data-layout='mobile'] .modal--kit .tt-dialog {
  width: 100%;
  max-width: none;
  max-height: 92dvh;
  border-bottom: 0;
  border-radius: var(--radius-overlay) var(--radius-overlay) 0 0;
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

[data-layout='mobile'] .modal--kit .tt-dialog__foot {
  flex-direction: column-reverse;
  align-items: stretch;
  gap: 8px;
}

[data-layout='mobile'] .modal--kit .tt-dialog__foot .tt-btn {
  width: 100%;
  height: var(--size-control-phone);
  font: var(--text-button-lg);
}

/* Every target is 44px on a phone: the dialog's Close cross and a toast's
 * Dismiss included (both are 32px compact icon buttons on a desktop). */
[data-layout='mobile'] .modal--kit .tt-dialog__head .tt-icon-btn,
[data-layout='mobile'] .toast__dismiss {
  width: var(--size-control-phone);
  height: var(--size-control-phone);
}

/* -- avatar picker ---------------------------------------------------------
 * The gallery for choosing a LiveAvatar (HeyGen) presenter (js/ui.js
 * avatarPickerModal; the studio's Choose avatar). The kit's dialog, widened:
 * this is a browse-and-compare screen, and fewer than four columns makes it
 * feel like a list. Tiles are portrait 3/4 because the previews are framed
 * head-and-shoulders; the caption sits over the image so a tile reads as one
 * photo. Token-only.
 */

.tt-dialog.apick {
  width: min(1040px, 100%);
  max-height: calc(100dvh - 160px);
}

.apick__titles {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.apick__subtitle {
  margin: 0;
  font: var(--text-body-sm);
  color: var(--color-ink-2);
}

.apick__toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 24px 12px;
  border-bottom: var(--rule-hair);
}

.apick__search {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 360px;
}

.apick__count {
  font: var(--text-body-sm);
  color: var(--color-ink-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.apick__toolbar .tt-btn {
  margin-left: auto;
}

.apick__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px 24px;
}

.apick__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(176px, 1fr));
  gap: 16px;
}

.apick__foot {
  gap: 16px;
  border-top: var(--rule-hair);
}

.apick__chosen {
  flex: 1 1 auto;
  min-width: 0;
  font: var(--text-body-sm);
  color: var(--color-ink-2);
}

.apick__chosen strong {
  color: var(--color-ink);
  font-weight: 600;
}

.apick__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}

/* a tile: the photo, the flags over its top edge, the name over its foot */
.atile {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 0;
  border: 1px solid var(--color-edge);
  border-radius: var(--radius-control);
  background: var(--color-surface-raised);
  color: var(--color-ink-on-navy);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  aspect-ratio: 3 / 4;
}

.atile:hover {
  border-color: var(--color-edge-strong);
}

.atile:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--color-ground), 0 0 0 4px var(--color-focus);
}

.atile[aria-pressed='true'] {
  border-color: var(--color-live-text);
  box-shadow: inset 0 0 0 2px var(--color-live-text);
}

.atile[disabled] {
  cursor: default;
  opacity: 0.55;
}

.atile__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  opacity: 0;
  transition: opacity 0.25s ease;
}

.atile__img[data-loaded='true'] {
  opacity: 1;
}

.atile__img--empty {
  display: grid;
  place-items: center;
  opacity: 1;
  font: var(--text-title-lg);
  color: var(--color-ink-muted-on-navy);
}

.atile__meta {
  position: relative;
  z-index: 1;
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 24px 10px 10px;
  background: var(--color-captions-scrim);
}

.atile__name {
  font: var(--text-button-sm);
  color: var(--color-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.atile__voice {
  font: var(--text-note);
  letter-spacing: var(--tracking-note);
  color: var(--color-ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.atile__flags {
  position: absolute;
  z-index: 1;
  top: 8px;
  left: 8px;
  right: 8px;
  display: flex;
  align-items: flex-start;
  gap: 4px;
  flex-wrap: wrap;
  pointer-events: none;
}

.atile__flag {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 6px;
  border-radius: var(--radius-control);
  background: var(--color-captions-scrim);
  font: var(--text-micro);
  color: var(--color-ink);
}

.atile__tick {
  display: none;
  margin-left: auto;
  width: 22px;
  height: 22px;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-control);
  background: var(--color-live-text);
  color: var(--color-primary-label);
}

.atile[aria-pressed='true'] .atile__tick {
  display: inline-flex;
}

.apick__state {
  grid-column: 1 / -1;
  padding: 16px 0;
}

.apick__skeleton {
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-control);
  background: var(--color-meter-track);
  animation: apick-shimmer 1.1s linear infinite;
}

@keyframes apick-shimmer {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

[data-layout='mobile'] .modal--kit .tt-dialog.apick {
  max-height: 92dvh;
}

[data-layout='mobile'] .apick__grid {
  grid-template-columns: repeat(auto-fill, minmax(122px, 1fr));
  gap: 12px;
}

[data-layout='mobile'] .apick__toolbar,
[data-layout='mobile'] .apick__body {
  padding-left: 16px;
  padding-right: 16px;
}

[data-layout='mobile'] .apick__toolbar {
  flex-wrap: wrap;
}

[data-layout='mobile'] .apick__search {
  max-width: none;
  flex-basis: 100%;
}

[data-layout='mobile'] .apick__toolbar .tt-btn {
  height: var(--size-control-phone);
}

[data-layout='mobile'] .apick__foot {
  flex-direction: column;
  align-items: stretch;
}

[data-layout='mobile'] .apick__actions {
  flex-direction: column-reverse;
  align-items: stretch;
}

@keyframes modal-in {
  from {
    opacity: 0;
    transform: translateY(10px) scale(0.985);
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
}

/* -- status dot ----------------------------------------------------------- */

/* -- utility -------------------------------------------------------------- */

.spacer {
  margin-left: auto;
}
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

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

  /* Named entrances are switched off outright, as the kit gates its spinner
     and orb, rather than left to the 0.01ms clamp above. */
  .toast,
  .modal,
  .modal__panel {
    animation: none;
  }
}
