/* ============================================================
   Thomas Bosshart — Component styles
   Single entry point, SHARED: heures/ and app/ both reach this file through
   their src/design/styles.css. Never reduce it to one consumer's slice — a
   2026-07-15 'reconciled subset' kept what study used and dropped 135
   selectors, every console pattern among them. heures renders those classes,
   so its portal shipped unstyled the next time it was rebuilt, 26 days later.
   A class with no rule fails nothing at build time.
   Real classes (so hover/focus/active work and stay themeable).
   JSX components apply these `tb-` classes. Calm by default;
   the one playful flourish is the accent card-hover nudge.
   Code blocks are ALWAYS dark (Direction C) — their chrome uses
   the --code-* tokens, never the page text tokens.
   ============================================================ */

/* ----------------------------- Button ----------------------------- */
.tb-btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-ui);
  font-weight: var(--fw-medium);
  font-size: var(--text-sm);
  line-height: 1;
  border-radius: var(--radius-sm);
  border: var(--border-width) solid transparent;
  padding: 0 var(--space-4); height: 36px;
  cursor: pointer; white-space: nowrap;
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.tb-btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.tb-btn--sm { height: 30px; padding: 0 var(--space-3); font-size: var(--text-xs); }
.tb-btn--lg { height: 42px; padding: 0 var(--space-5); font-size: var(--text-md); }
.tb-btn[disabled], .tb-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; pointer-events: none; }
.tb-btn__icon { width: 1em; height: 1em; flex: none; }

.tb-btn--primary { background: var(--accent); color: var(--text-on-accent); }
.tb-btn--primary:hover { background: var(--accent-hover); }
.tb-btn--secondary { background: var(--color-surface); color: var(--text-body); border-color: var(--border); }
.tb-btn--secondary:hover { background: var(--color-surface-hover); border-color: var(--border-strong); }
.tb-btn--ghost { background: transparent; color: var(--text-body); }
.tb-btn--ghost:hover { background: var(--color-surface-hover); }
.tb-btn--danger { background: var(--danger); color: #fff; }
.tb-btn--danger:hover { filter: brightness(1.06); }

/* --------------------------- Icon button --------------------------- */
.tb-iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: var(--radius-sm);
  border: var(--border-width) solid transparent; background: transparent;
  color: var(--text-muted); cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.tb-iconbtn:hover { background: var(--color-surface-hover); color: var(--text-body); }
.tb-iconbtn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.tb-iconbtn svg { width: 18px; height: 18px; }

/* ----------------------------- Badge ------------------------------ */
.tb-badge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  font-family: var(--font-ui);
  font-size: var(--text-2xs); font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-wide);
  padding: 0.2em 0.6em; border-radius: var(--radius-sm);
  border: var(--border-width) solid transparent; line-height: 1.35;
  white-space: nowrap;
}
.tb-badge--mono { font-family: var(--font-mono); letter-spacing: 0; text-transform: none; }
.tb-badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.tb-badge--neutral  { background: var(--color-surface-sunken); color: var(--text-muted); border-color: var(--border-soft); }
.tb-badge--accent   { background: var(--accent-soft); color: var(--accent-text); border-color: var(--accent-border); }
.tb-badge--positive { background: var(--positive-soft); color: var(--positive); border-color: color-mix(in srgb, var(--positive) 22%, transparent); }
.tb-badge--danger   { background: var(--danger-soft); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 22%, transparent); }
.tb-badge--warning  { background: var(--warning-soft); color: var(--warning); border-color: color-mix(in srgb, var(--warning) 24%, transparent); }
.tb-badge--info     { background: var(--info-soft); color: var(--info); border-color: color-mix(in srgb, var(--info) 22%, transparent); }

/* ------------------------------ TopNav ----------------------------- */
.tb-nav {
  position: sticky; top: 0; z-index: var(--z-nav);
  height: var(--nav-height);
  display: flex; align-items: center; gap: var(--space-5);
  padding: 0 var(--space-6);
  background: color-mix(in srgb, var(--color-surface) 82%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  -webkit-backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: var(--rule);
}
.tb-nav__brand { display: inline-flex; align-items: center; gap: var(--space-2); text-decoration: none; color: var(--text-strong); }
/* Brand mark — decision postponed; slot kept. Always currentColor/accent,
   sized to harmonise with the lockup text, never larger than it. */
.tb-nav__mark {
  display: inline-grid; place-items: center; width: 20px; height: 24px;
  background: none; color: var(--accent);
}
.tb-nav__mark svg { width: 16px; height: 16px; display: block; }
.tb-nav__name { font-weight: var(--fw-semibold); font-size: var(--text-sm); letter-spacing: var(--tracking-tight); }
.tb-nav__name .tb-nav__sub { color: var(--text-faint); font-weight: var(--fw-regular); }
.tb-nav__links { display: flex; align-items: center; gap: var(--space-1); margin-left: var(--space-3); }
.tb-nav__link {
  font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-muted);
  text-decoration: none; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
  transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.tb-nav__link:hover { color: var(--text-strong); background: var(--color-surface-hover); text-decoration: none; }
.tb-nav__link.is-active { color: var(--accent-text); }
.tb-nav__spacer { flex: 1 1 auto; }
.tb-nav__actions { display: flex; align-items: center; gap: var(--space-1); }
.tb-nav__search {
  display: inline-flex; align-items: center; gap: var(--space-2);
  height: 34px; padding: 0 var(--space-3); min-width: 180px;
  background: var(--color-surface-sunken); border: var(--border-width) solid var(--border-soft);
  border-radius: var(--radius-sm); color: var(--text-faint); font-size: var(--text-sm); cursor: text;
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.tb-nav__search:hover { border-color: var(--border); }
.tb-nav__search svg { width: 15px; height: 15px; }
.tb-nav__kbd {
  margin-left: auto; font-family: var(--font-mono); font-size: var(--text-2xs);
  color: var(--text-faint); background: var(--color-surface); border: var(--border-width) solid var(--border-soft);
  border-radius: var(--radius-xs); padding: 1px 5px;
}

/* ----------------------------- TocSidebar -------------------------- */
.tb-toc { font-family: var(--font-ui); }
.tb-toc__label {
  font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps);
  font-weight: var(--fw-semibold); color: var(--text-faint); margin-bottom: var(--space-3);
}
.tb-toc__list { list-style: none; margin: 0; padding: 0; border-left: var(--border-width) solid var(--border-soft); }
.tb-toc__link {
  display: block; font-size: var(--text-sm); line-height: var(--leading-snug);
  color: var(--text-muted); text-decoration: none;
  padding: var(--space-1) 0 var(--space-1) var(--space-3);
  margin-left: -1px; border-left: var(--border-width-2) solid transparent;
  transition: color var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
}
.tb-toc__link:hover { color: var(--text-strong); text-decoration: none; }
.tb-toc__link.is-active { color: var(--accent-text); border-left-color: var(--accent); font-weight: var(--fw-medium); }
.tb-toc__link--l3 { padding-left: var(--space-6); font-size: var(--text-xs); }

/* ----------------------------- CodeBlock --------------------------- */
.tb-code {
  border: var(--border-width) solid var(--code-border);
  border-radius: var(--radius-md); overflow: hidden;
  background: var(--code-bg); margin: var(--space-5) 0;
}
.tb-code__head {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-4);
  background: var(--code-surface); border-bottom: var(--border-width) solid var(--code-border);
}
.tb-code__name { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--code-muted); }
.tb-code__lang {
  font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--code-faint);
  text-transform: lowercase; letter-spacing: var(--tracking-wide);
  border: var(--border-width) solid var(--code-border); border-radius: var(--radius-xs); padding: 1px 6px;
}
.tb-code__spacer { flex: 1; }
.tb-code__copy {
  display: inline-flex; align-items: center; gap: var(--space-1);
  font-family: var(--font-ui); font-size: var(--text-2xs); color: var(--code-muted);
  background: transparent; border: var(--border-width) solid transparent; border-radius: var(--radius-xs);
  padding: var(--space-1) var(--space-2); cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.tb-code__copy:hover { color: var(--code-accent); background: var(--code-hover); }
.tb-code__copy svg { width: 13px; height: 13px; }
.tb-code__body { margin: 0; padding: var(--space-4); overflow-x: auto; }
.tb-code__body code {
  font-family: var(--font-mono); font-size: var(--text-code); line-height: var(--leading-code);
  color: var(--syn-var); display: block; white-space: pre; tab-size: 4;
}
.tb-code--numbered .tb-code__body { counter-reset: ln; padding-left: 0; }
.tb-code--numbered .tb-line { display: block; counter-increment: ln; padding-left: 3.4em; position: relative; }
.tb-code--numbered .tb-line::before {
  content: counter(ln); position: absolute; left: 0; width: 2.4em; text-align: right;
  color: var(--code-faint); opacity: .8; user-select: none;
}
.tok-kw  { color: var(--syn-kw); }
.tok-fn  { color: var(--syn-fn); }
.tok-str { color: var(--syn-str); }
.tok-num { color: var(--syn-num); }
.tok-com { color: var(--syn-com); font-style: italic; }
.tok-pun { color: var(--syn-pun); }
.tok-var { color: var(--syn-var); }

/* ------------------------------ Callout ---------------------------- */
/* A boxed aside — RARE by design. Reading-first means most explanation flows
   as prose; a Callout is reserved for the three things that genuinely
   interrupt: a quiet aside (note), a thing to memorise (takeaway), or a
   warning (pitfall). Lighter chrome than v1 — no full-height accent bar on
   the quiet tones, smaller label, tighter padding. */
.tb-callout {
  display: flex; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); border-radius: var(--radius-md);
  background: var(--color-surface-sunken); border: var(--border-width) solid var(--border-soft);
  margin: var(--space-5) 0;
}
.tb-callout__icon { flex: none; width: 16px; height: 16px; color: var(--text-faint); margin-top: 2px; }
.tb-callout__icon svg { width: 100%; height: 100%; }
.tb-callout__body { min-width: 0; }
.tb-callout__title { font-family: var(--font-ui); font-weight: var(--fw-semibold); font-size: var(--text-xs); color: var(--text-strong); margin-bottom: var(--space-1); }
.tb-callout__text { font-size: var(--text-sm); line-height: var(--leading-snug); color: var(--text-body); }
.tb-callout__text > * + * { margin-top: var(--space-2); }

/* Quiet asides — no colored edge, just a subtle well + faint icon */
.tb-callout--note,
.tb-callout--info { background: var(--color-surface-sunken); }
.tb-callout--note .tb-callout__icon,
.tb-callout--info .tb-callout__icon { color: var(--text-faint); }

/* Takeaway (« À retenir ») — the accent note you should commit to memory */
.tb-callout--tip,
.tb-callout--takeaway {
  background: var(--accent-soft); border-color: var(--accent-border);
  border-left: var(--border-width-2) solid var(--accent);
}
.tb-callout--tip .tb-callout__icon, .tb-callout--takeaway .tb-callout__icon,
.tb-callout--tip .tb-callout__title, .tb-callout--takeaway .tb-callout__title { color: var(--accent-text); }

/* Pitfall (« Piège ») — a real warning / common mistake */
.tb-callout--warning {
  background: var(--warning-soft); border-color: color-mix(in srgb, var(--warning) 22%, transparent);
  border-left: var(--border-width-2) solid var(--warning);
}
.tb-callout--warning .tb-callout__icon, .tb-callout--warning .tb-callout__title { color: var(--warning); }
.tb-callout--danger,
.tb-callout--pitfall {
  background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger) 20%, transparent);
  border-left: var(--border-width-2) solid var(--danger);
}
.tb-callout--danger .tb-callout__icon, .tb-callout--pitfall .tb-callout__icon,
.tb-callout--danger .tb-callout__title, .tb-callout--pitfall .tb-callout__title { color: var(--danger); }

/* Concept clé — a BOXED definition, for the 1–3 anchor concepts of a section.
   Use sparingly: ordinary definitions flow as .tb-def. This is the legitimate
   “box for clarity” — calm slate, distinct from the emphasis tones. */
.tb-callout--concept { background: var(--info-soft); border-color: color-mix(in srgb, var(--info) 18%, transparent); border-left: var(--border-width-2) solid var(--info); }
.tb-callout--concept .tb-callout__icon, .tb-callout--concept .tb-callout__title { color: var(--info); }

/* ------------------------------ Table ------------------------------ */
.tb-table-wrap { overflow-x: auto; border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-md); margin: var(--space-5) 0; }
.tb-table { width: 100%; border-collapse: collapse; font-family: var(--font-ui); font-size: var(--text-sm); }
.tb-table caption { caption-side: top; text-align: left; padding: var(--space-3) var(--space-4) 0; color: var(--text-muted); font-size: var(--text-xs); }
.tb-table thead th {
  text-align: left; font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps);
  font-weight: var(--fw-semibold); color: var(--text-faint);
  padding: var(--space-3) var(--space-4); background: var(--color-surface-sunken);
  border-bottom: var(--border-width) solid var(--border);
  /* Parks at the top of whatever scrolls it. A consumer with its own sticky bar
     above the table overrides `top` in its own CSS (app: .subject) — an offset
     baked in here floats the header over the body in every consumer that has no
     such bar. */
  position: sticky; top: 0; white-space: nowrap;
}
.tb-table tbody td {
  padding: var(--space-3) var(--space-4); color: var(--text-body);
  border-bottom: var(--border-width) solid var(--border-soft); vertical-align: top;
}
.tb-table tbody tr:last-child td { border-bottom: none; }
.tb-table tbody tr:hover td { background: color-mix(in srgb, var(--accent-soft) 50%, transparent); }
.tb-table--zebra tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--color-surface-sunken) 55%, transparent); }
.tb-table .is-num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.tb-table .is-strong { font-weight: var(--fw-semibold); color: var(--text-strong); }
.tb-table .is-positive { color: var(--positive); font-weight: var(--fw-medium); }
.tb-table .is-danger { color: var(--danger); font-weight: var(--fw-medium); }
.tb-table .is-muted { color: var(--text-faint); }

/* --------------------------- TopicCard ----------------------------- */
.tb-card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-5); text-decoration: none;
  background: var(--color-surface); border: var(--border-width) solid var(--border-soft);
  border-radius: var(--radius-md); color: inherit; position: relative;
  transition: border-color var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-spring),
              box-shadow var(--dur-base) var(--ease-standard);
}
/* the one playful detail: accent-edged lift + arrow nudge on hover */
.tb-card:hover { border-color: var(--accent-border); transform: translateY(-3px); box-shadow: var(--shadow-md); text-decoration: none; }
.tb-card:hover .tb-card__arrow { transform: translateX(3px); color: var(--accent); }
.tb-card__top { display: flex; align-items: center; justify-content: space-between; }
.tb-card__icon { width: 26px; height: 26px; color: var(--accent); }
.tb-card__icon svg { width: 100%; height: 100%; }
.tb-card__arrow { color: var(--text-faint); transition: transform var(--dur-base) var(--ease-spring), color var(--dur-base) var(--ease-standard); }
.tb-card__arrow svg { width: 16px; height: 16px; }
.tb-card__title { font-family: var(--font-display); font-weight: var(--fw-semibold); font-size: var(--text-md); color: var(--text-strong); letter-spacing: var(--tracking-tight); }
.tb-card__desc { font-size: var(--text-sm); line-height: var(--leading-snug); color: var(--text-muted); }
.tb-card__meta { display: flex; align-items: center; gap: var(--space-3); margin-top: auto; padding-top: var(--space-2); font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); }
.tb-card__meta-item { display: inline-flex; align-items: center; gap: var(--space-1); }

.tb-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-4); }

/* ------------------------------ Field ------------------------------ */
/* text input / select — used by forms (timesheet entry, future CV, etc.) */
.tb-field {
  font-family: var(--font-ui); font-size: var(--text-sm); color: var(--text-body);
  background: var(--color-surface); border: var(--border-width) solid var(--border);
  border-radius: var(--radius-sm); padding: 0 var(--space-3); height: 36px; width: 100%;
  transition: border-color var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard);
}
.tb-field::placeholder { color: var(--text-faint); }
.tb-field:hover { border-color: var(--border-strong); }
.tb-field:focus { outline: none; border-color: var(--accent); box-shadow: var(--shadow-focus); }
select.tb-field { cursor: pointer; }

/* ------------------------- Segmented control ----------------------- */
/* used for the timesheet company switcher and any 2–4 option toggle */
.tb-seg { display: inline-flex; gap: 2px; padding: 3px; background: var(--color-surface-sunken); border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-md); }
.tb-seg__btn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-family: var(--font-ui); font-size: var(--text-sm); font-weight: var(--fw-medium);
  color: var(--text-muted); background: transparent; border: none; cursor: pointer;
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.tb-seg__btn:hover { color: var(--text-strong); }
.tb-seg__btn.is-active { background: var(--color-surface); color: var(--text-strong); box-shadow: var(--shadow-xs); }
.tb-seg__btn:disabled { color: var(--text-faint); cursor: not-allowed; }
.tb-seg__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

/* --------------------- PageToc (floating "on this page") ----------- */
.tb-pagetoc { position: fixed; right: var(--space-6); bottom: var(--space-6); z-index: var(--z-sticky); font-family: var(--font-ui); }
.tb-pagetoc--inline { position: absolute; }
.tb-pagetoc__pill {
  position: relative; display: inline-flex; align-items: stretch; overflow: hidden;
  background: color-mix(in srgb, var(--color-surface) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(10px); -webkit-backdrop-filter: saturate(1.4) blur(10px);
  border: var(--border-width) solid var(--border); border-radius: var(--radius-full);
  box-shadow: var(--shadow-md);
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.tb-pagetoc__pill:hover { border-color: var(--accent-border); }
.tb-pagetoc__top {
  display: grid; place-items: center; width: 38px; flex: none;
  background: transparent; border: none; border-right: var(--border-width) solid var(--border-soft);
  color: var(--text-muted); cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.tb-pagetoc__top:hover { color: var(--accent-text); background: var(--color-surface-hover); }
.tb-pagetoc__top svg { width: 15px; height: 15px; }
.tb-pagetoc__main {
  display: inline-flex; align-items: center; gap: var(--space-2);
  height: 40px; padding: 0 var(--space-2) 0 var(--space-4);
  background: transparent; border: none; cursor: pointer;
  color: var(--text-body); font-family: var(--font-ui); font-size: var(--text-sm); font-weight: var(--fw-medium);
  transition: background var(--dur-fast) var(--ease-standard);
}
.tb-pagetoc__main:hover { background: var(--color-surface-hover); }
.tb-pagetoc__ico { width: 16px; height: 16px; color: var(--text-faint); flex: none; }
.tb-pagetoc__ico svg { width: 100%; height: 100%; }
.tb-pagetoc__now { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-strong); }
.tb-pagetoc__count { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); background: var(--color-surface-sunken); border-radius: var(--radius-full); padding: 3px 8px; }
.tb-pagetoc__bar { position: absolute; left: 0; bottom: 0; height: 2px; background: var(--accent); transition: width var(--dur-fast) linear; }
.tb-pagetoc__panel {
  position: absolute; right: 0; bottom: calc(40px + var(--space-2)); min-width: 232px; max-width: 300px;
  background: var(--color-surface); border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: var(--space-3);
  animation: tb-pagetoc-in var(--dur-fast) var(--ease-out);
}
@keyframes tb-pagetoc-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.tb-pagetoc__label { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps); font-weight: var(--fw-semibold); color: var(--text-faint); padding: 0 var(--space-2) var(--space-2); }
.tb-pagetoc__list { list-style: none; margin: 0; padding: 0; }
.tb-pagetoc__link {
  display: flex; align-items: center; gap: var(--space-2); width: 100%; text-align: left;
  font-size: var(--text-sm); color: var(--text-muted); background: none; border: none; cursor: pointer;
  padding: var(--space-2); border-radius: var(--radius-sm); line-height: var(--leading-snug);
  transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.tb-pagetoc__link:hover { background: var(--color-surface-hover); color: var(--text-strong); }
.tb-pagetoc__link.is-active { color: var(--accent-text); font-weight: var(--fw-medium); }
.tb-pagetoc__link--l3 { padding-left: var(--space-6); font-size: var(--text-xs); }
.tb-pagetoc__tick { width: 5px; height: 5px; border-radius: 50%; background: var(--border-strong); flex: none; }
.tb-pagetoc__link.is-active .tb-pagetoc__tick { background: var(--accent); }

/* ============================================================
   THEORY TEMPLATE SET — the boxed blocks
   The prose spine (prose / lead / definition / steps / worked)
   lives in tokens/base.css and FLOWS. Only the two blocks below
   keep a box, because they earn it: Drill is interactive, Figure
   needs a frame. Tables (.tb-table) and code (.tb-code) above are
   the other two chromed blocks. Everything else reads as prose.
   ============================================================ */

/* ---- Drill (BOXED) — inline self-test: prompt → reveal solution ---- */
.tb-drill {
  border: var(--border-width) solid var(--border); border-radius: var(--radius-md);
  background: var(--color-surface); margin: var(--space-5) 0; overflow: hidden;
}
.tb-drill > summary {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); cursor: pointer; list-style: none;
  font-weight: var(--fw-medium); color: var(--text-strong); line-height: var(--leading-snug);
}
.tb-drill > summary::-webkit-details-marker { display: none; }
.tb-drill > summary:hover { background: var(--color-surface-hover); }
.tb-drill__lab {
  font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps);
  font-weight: var(--fw-semibold); color: var(--accent-text);
  border: var(--border-width) solid var(--accent-border); background: var(--accent-soft);
  border-radius: var(--radius-xs); padding: 2px 6px; flex: none; margin-top: 1px; white-space: nowrap;
}
.tb-drill__q { flex: 1 1 auto; min-width: 0; }
.tb-drill__chev { flex: none; color: var(--text-faint); margin-top: 2px; transition: transform var(--dur-fast) var(--ease-standard); }
.tb-drill__chev svg { width: 16px; height: 16px; display: block; }
.tb-drill[open] .tb-drill__chev { transform: rotate(90deg); }
.tb-drill__reveal {
  padding: var(--space-3) var(--space-4) var(--space-4);
  border-top: var(--border-width) solid var(--border-soft);
  background: var(--color-surface-sunken);
  font-size: var(--text-sm); line-height: var(--leading-snug); color: var(--text-body);
}
.tb-drill__reveal > * + * { margin-top: var(--space-2); }

/* ---- Figure (BOXED) — SVG diagram + caption, on the diagram palette ---- */
.tb-figure { margin: var(--space-6) 0; }
.tb-figure__frame {
  border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-md);
  background: var(--color-surface); padding: var(--space-5);
  display: grid; place-items: center; overflow-x: auto;
}
.tb-figure svg { max-width: 100%; height: auto; }
.tb-figure__cap {
  margin: var(--space-2) 0 0; font-size: var(--text-xs); color: var(--text-muted);
  display: flex; gap: var(--space-2); line-height: var(--leading-snug);
}
.tb-figure__cap b { color: var(--text-body); font-weight: var(--fw-semibold); }

/* SVG palette helpers — apply inside any figure instead of raw hex.
   (Or set stroke/fill to var(--fig-…) directly.) */
.fig-ink    { fill: var(--fig-ink); }
.fig-muted  { fill: var(--fig-muted); }
.fig-grid   { stroke: var(--fig-grid); }
.fig-axis   { stroke: var(--fig-axis); }
.fig-edge   { stroke: var(--fig-edge); }
.fig-node   { fill: var(--fig-node); stroke: var(--fig-node-ink); }
.fig-s1 { fill: var(--fig-series-1); }  .fig-s1-stroke { stroke: var(--fig-series-1); }
.fig-s2 { fill: var(--fig-series-2); }  .fig-s2-stroke { stroke: var(--fig-series-2); }
.fig-s3 { fill: var(--fig-series-3); }  .fig-s3-stroke { stroke: var(--fig-series-3); }
.fig-s4 { fill: var(--fig-series-4); }  .fig-s4-stroke { stroke: var(--fig-series-4); }
.fig-good { fill: var(--fig-good); }    .fig-good-stroke { stroke: var(--fig-good); }
.fig-bad  { fill: var(--fig-bad); }     .fig-bad-stroke { stroke: var(--fig-bad); }
.fig-accent { fill: var(--fig-accent); } .fig-accent-stroke { stroke: var(--fig-accent); }
.fig-highlight { fill: var(--fig-highlight); }

/* ============================================================
   QUIZ / QUESTIONS — the Examen at the end of a subject
   Multiple types: QCM, Vrai/Faux, Réponse libre, and CODE questions
   (a snippet → guess the output or the complexity; the solution
   shows code). Scored & tested only here — the in-theory self-test
   is .tb-drill. Restyle once → every subject's exam follows.
   ============================================================ */
.tb-quiz { background: var(--color-surface); border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-md); padding: var(--space-5); margin-bottom: var(--space-4); }
.tb-quiz__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-2); min-height: 22px; }
.tb-quiz__n { font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-faint); }
.tb-quiz__meta { display: inline-flex; align-items: center; gap: var(--space-3); }
.tb-quiz__type { font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-faint); border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-full); padding: 1px var(--space-2); }
.tb-quiz__prompt { font-size: var(--text-md); font-weight: var(--fw-medium); color: var(--text-strong); margin: 0 0 var(--space-4); line-height: var(--leading-snug); }
/* a code snippet the question is ABOUT — sits under the prompt */
.tb-quiz__code { margin: 0 0 var(--space-4); }
.tb-quiz__code .tb-code { margin: 0; }
.tb-quiz__opts { display: flex; flex-direction: column; gap: var(--space-2); }
.tb-quiz__opt { display: flex; align-items: center; gap: var(--space-3); text-align: left; font-family: var(--font-ui); font-size: var(--text-sm); color: var(--text-body); background: var(--color-surface); border: var(--border-width) solid var(--border); border-radius: var(--radius-sm); padding: var(--space-3); cursor: pointer; transition: border-color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard); }
.tb-quiz__opt:hover:not(:disabled) { border-color: var(--accent-border); background: var(--color-surface-hover); }
.tb-quiz__opt:disabled { cursor: default; }
.tb-quiz__opt code { font-family: var(--font-mono); }
.tb-quiz__key { width: 22px; height: 22px; flex: none; display: grid; place-items: center; font-family: var(--font-mono); font-size: var(--text-2xs); border-radius: var(--radius-sm); background: var(--color-surface-sunken); color: var(--text-muted); }
.tb-quiz__opt.is-correct { border-color: color-mix(in srgb, var(--positive) 45%, transparent); background: var(--positive-soft); color: var(--positive); }
.tb-quiz__opt.is-correct .tb-quiz__key { background: var(--positive); color: var(--text-on-accent); }
.tb-quiz__opt.is-wrong { border-color: color-mix(in srgb, var(--danger) 45%, transparent); background: var(--danger-soft); color: var(--danger); }
.tb-quiz__opt.is-wrong .tb-quiz__key { background: var(--danger); color: var(--text-on-accent); }
.tb-quiz__tf { display: flex; gap: var(--space-2); }
.tb-quiz__opt--tf { flex: 1; justify-content: center; font-weight: var(--fw-medium); }
.tb-quiz__why { list-style: none; margin: var(--space-3) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.tb-quiz__why li { display: flex; gap: var(--space-3); font-size: var(--text-sm); line-height: var(--leading-snug); }
.tb-quiz__why-key { width: 20px; height: 20px; flex: none; display: grid; place-items: center; font-family: var(--font-mono); font-size: var(--text-2xs); border-radius: var(--radius-sm); margin-top: 1px; }
.tb-quiz__why li.is-correct .tb-quiz__why-key { background: var(--positive); color: var(--text-on-accent); }
.tb-quiz__why li.is-wrong .tb-quiz__why-key { background: var(--color-surface-sunken); color: var(--text-faint); }
.tb-quiz__why-txt { color: var(--text-muted); }
.tb-quiz__why li.is-correct .tb-quiz__why-txt { color: var(--text-body); }
.tb-quiz__why-txt b { color: var(--text-strong); font-weight: var(--fw-semibold); }
.tb-quiz__textarea { width: 100%; box-sizing: border-box; font-family: var(--font-ui); font-size: var(--text-sm); color: var(--text-body); background: var(--color-bg); border: var(--border-width) solid var(--border); border-radius: var(--radius-sm); padding: var(--space-3); resize: vertical; line-height: var(--leading-snug); transition: border-color var(--dur-fast) var(--ease-standard); }
.tb-quiz__textarea:focus { outline: none; border-color: var(--accent-border); box-shadow: var(--shadow-focus); }
.tb-quiz__hint { font-size: var(--text-xs); color: var(--text-faint); margin: var(--space-2) 0 0; }
.tb-quiz__actions { margin-top: var(--space-3); }
.tb-quiz__solution { margin-top: var(--space-3); font-size: var(--text-sm); line-height: var(--leading-snug); color: var(--text-body); background: var(--accent-soft); border-left: var(--border-width-2) solid var(--accent-border); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; padding: var(--space-3) var(--space-4); }
.tb-quiz__solution > p { margin: 0; }
.tb-quiz__solution b { color: var(--text-strong); font-weight: var(--fw-semibold); }
.tb-quiz__solution .tb-code { margin: var(--space-3) 0 0; }
.tb-quiz__solution-tag { display: block; font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps); font-weight: var(--fw-semibold); color: var(--accent-text); margin-bottom: var(--space-1); }
.tb-quiz__self { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-3); flex-wrap: wrap; }
.tb-quiz__self-label { font-size: var(--text-sm); color: var(--text-muted); margin-right: var(--space-1); }
.tb-quiz__self-btn { font-family: var(--font-ui); font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-muted); background: var(--color-surface); border: var(--border-width) solid var(--border); border-radius: var(--radius-sm); padding: var(--space-1) var(--space-3); cursor: pointer; transition: color var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard); }
.tb-quiz__self-btn--ok:hover, .tb-quiz__self-btn--ok.is-on { color: var(--positive); border-color: color-mix(in srgb, var(--positive) 45%, transparent); background: var(--positive-soft); }
.tb-quiz__self-btn--no:hover, .tb-quiz__self-btn--no.is-on { color: var(--warning); border-color: color-mix(in srgb, var(--warning) 45%, transparent); background: var(--warning-soft); }

/* ============================================================
   ASSISTANT IA — a docked, EPHEMERAL study companion
   One panel, summoned from the PageToc pill, that reads "where you
   are" (the contexte chip) and answers in the moment. No sessions,
   no history: it caps at ~5 messages and resets when closed. Calm
   by design — hairline, accent emerald, mono labels. No avatars, no
   gradients, no chat bubbles. Every AI-authored bit wears .tb-ai-badge
   so it stays visually honest vs. human-written notes.
   ============================================================ */

/* ---- The honest "IA" marker — wherever a model wrote something ---- */
.tb-ai-badge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: var(--fw-medium);
  text-transform: uppercase; letter-spacing: var(--tracking-caps);
  color: var(--accent-text); background: var(--accent-soft);
  border: var(--border-width) solid var(--accent-border); border-radius: var(--radius-full);
  padding: 1px var(--space-2); line-height: 1.5; white-space: nowrap;
}
.tb-ai-badge svg { width: 11px; height: 11px; flex: none; }

/* ---- Floating panel — detached from the edge (rounded, with margins,
   a "big pill"), anchored bottom-right ABOVE the PageToc pill. It does NOT
   cover the site: the page content wrapper gets margin-right while open so
   no text passes under it, and the pill stays visible. Closes by clicking
   its own logo OR the top close button.
   On the site: panel is .tb-ai--floating (position:fixed); the content
   region gets `margin-right: calc(var(--ai-width) + var(--space-10))`
   under a parent [data-ai-open], transitioned on margin-right. ---- */
.tb-ai {
  display: flex; flex-direction: column;
  width: var(--ai-width, 380px); max-height: 100%;
  background: var(--color-surface); border: var(--border-width) solid var(--border);
  border-radius: var(--radius-lg); overflow: hidden;
  font-family: var(--font-ui);
}
.tb-ai--floating {
  position: fixed; right: var(--space-6); bottom: calc(var(--space-6) + 52px);
  width: var(--ai-width, 380px); max-height: min(70vh, 620px); box-shadow: var(--shadow-lg); z-index: var(--z-sticky);
  animation: tb-ai-rise var(--dur-base) var(--ease-out);
}
/* Page-push: a content region that yields room to the floating panel so it
   never covers text. Mark it .tb-ai-pushable; the open state is signalled by
   [data-ai-open] on a stable ancestor (e.g. <html>). The pill stays visible. */
.tb-ai-pushable { transition: margin-right var(--dur-base) var(--ease-standard); }
[data-ai-open] .tb-ai-pushable { margin-right: calc(var(--ai-width, 380px) + var(--space-10)); }
@media (max-width: 720px) { [data-ai-open] .tb-ai-pushable { margin-right: 0; } }
@keyframes tb-ai-rise { from { opacity: 0; transform: translateY(10px) scale(.99); } to { opacity: 1; transform: none; } }
.tb-ai__head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-3);
  border-bottom: var(--border-width) solid var(--border-soft); flex: none;
}
/* logo + title = a button; clicking it closes the panel */
.tb-ai__brand {
  display: inline-flex; align-items: center; gap: var(--space-2);
  background: transparent; border: none; cursor: pointer; padding: var(--space-1) var(--space-2);
  margin: calc(var(--space-1) * -1) 0 calc(var(--space-1) * -1) calc(var(--space-1) * -1);
  border-radius: var(--radius-sm); color: inherit;
  transition: background var(--dur-fast) var(--ease-standard);
}
.tb-ai__brand:hover { background: var(--color-surface-hover); }
.tb-ai__mark { width: 16px; height: 16px; color: var(--accent); flex: none; }
.tb-ai__mark svg { width: 100%; height: 100%; display: block; }
.tb-ai__title { font-weight: var(--fw-semibold); font-size: var(--text-sm); color: var(--text-strong); letter-spacing: var(--tracking-tight); }
.tb-ai__ephemeral { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); margin-left: var(--space-1); }
.tb-ai__head-sp { flex: 1; }

/* contexte chip — the only thing telling you what the model can see */
.tb-ai__context {
  display: flex; align-items: center; gap: var(--space-2); flex: none;
  margin: var(--space-3) var(--space-3) 0; padding: var(--space-2) var(--space-3);
  background: var(--accent-soft); border: var(--border-width) solid var(--accent-border);
  border-radius: var(--radius-md); min-width: 0;
}
.tb-ai__context svg { width: 14px; height: 14px; color: var(--accent-text); flex: none; }
.tb-ai__context-lab { font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--accent-text); flex: none; }
.tb-ai__context-now { font-size: var(--text-xs); color: var(--text-strong); font-weight: var(--fw-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

/* scrolling message area */
.tb-ai__body { flex: 1 1 auto; overflow-y: auto; padding: var(--space-4) var(--space-3); display: flex; flex-direction: column; gap: var(--space-4); }
.tb-ai__msg { font-size: var(--text-sm); line-height: var(--leading-snug); }
.tb-ai__msg--user {
  align-self: flex-end; max-width: 85%;
  background: var(--color-surface-sunken); border: var(--border-width) solid var(--border-soft);
  border-radius: var(--radius-md); padding: var(--space-2) var(--space-3); color: var(--text-body);
}
.tb-ai__msg--ai { align-self: stretch; color: var(--text-body); }
.tb-ai__msg--ai .tb-ai__ai-lab { display: inline-flex; align-items: center; gap: var(--space-1); margin-bottom: var(--space-2); }
.tb-ai__msg--ai p { margin: 0; }
.tb-ai__msg--ai p + p { margin-top: var(--space-2); }
.tb-ai__msg--ai code { font-family: var(--font-mono); font-size: 0.92em; color: var(--accent-text); }
/* grounding source — what the answer is based on (cited, not invented) */
.tb-ai__source { display: inline-flex; align-items: center; gap: var(--space-1); margin-top: var(--space-2); font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); }
.tb-ai__source svg { width: 11px; height: 11px; flex: none; }
.tb-ai__source b { color: var(--text-muted); font-weight: var(--fw-medium); }

/* thinking state — three calm dots */
.tb-ai__thinking { display: inline-flex; align-items: center; gap: 5px; padding: var(--space-1) 0; }
.tb-ai__thinking span { width: 5px; height: 5px; border-radius: 50%; background: var(--text-faint); animation: tb-ai-blink 1.2s var(--ease-standard) infinite; }
.tb-ai__thinking span:nth-child(2) { animation-delay: .18s; }
.tb-ai__thinking span:nth-child(3) { animation-delay: .36s; }
@keyframes tb-ai-blink { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

/* empty state */
.tb-ai__empty { margin: auto 0; text-align: center; color: var(--text-muted); font-size: var(--text-sm); line-height: var(--leading-snug); padding: var(--space-6) var(--space-2); }
.tb-ai__empty svg { width: 22px; height: 22px; color: var(--text-faint); margin-bottom: var(--space-3); }
.tb-ai__empty b { display: block; color: var(--text-strong); font-weight: var(--fw-semibold); margin-bottom: var(--space-1); }

/* keep-for-later — distinct from the chat: saves the gap to the backlog */
.tb-ai__keep {
  display: inline-flex; align-items: center; gap: var(--space-1); align-self: flex-start;
  font-family: var(--font-ui); font-size: var(--text-2xs); color: var(--text-muted);
  background: transparent; border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-2); cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.tb-ai__keep:hover { color: var(--accent-text); border-color: var(--accent-border); background: var(--accent-soft); }
.tb-ai__keep svg { width: 12px; height: 12px; }
.tb-ai__keep.is-kept { color: var(--accent-text); border-color: var(--accent-border); background: var(--accent-soft); }

/* composer */
.tb-ai__foot { flex: none; border-top: var(--border-width) solid var(--border-soft); padding: var(--space-3); }
.tb-ai__cap { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-2); }
.tb-ai__cap-n { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); font-variant-numeric: tabular-nums; }
.tb-ai__cap-n b { color: var(--text-muted); font-weight: var(--fw-semibold); }
.tb-ai__cap.is-near .tb-ai__cap-n b { color: var(--warning); }
.tb-ai__cap-note { font-family: var(--font-ui); font-size: var(--text-2xs); color: var(--text-faint); }
.tb-ai__composer { display: flex; align-items: flex-end; gap: var(--space-2); }
.tb-ai__input {
  flex: 1; box-sizing: border-box; resize: none; min-height: 38px; max-height: 120px;
  font-family: var(--font-ui); font-size: var(--text-sm); color: var(--text-body); line-height: var(--leading-snug);
  background: var(--color-bg); border: var(--border-width) solid var(--border); border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  transition: border-color var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard);
}
.tb-ai__input::placeholder { color: var(--text-faint); }
.tb-ai__input:focus { outline: none; border-color: var(--accent); box-shadow: var(--shadow-focus); }
.tb-ai__send { flex: none; width: 38px; height: 38px; display: grid; place-items: center; border-radius: var(--radius-sm); border: none; background: var(--accent); color: var(--text-on-accent); cursor: pointer; transition: background var(--dur-fast) var(--ease-standard); }
.tb-ai__send:hover { background: var(--accent-hover); }
.tb-ai__send:disabled { opacity: .45; cursor: not-allowed; }
.tb-ai__send svg { width: 16px; height: 16px; }

/* cap reached — composer locks, a calm reset notice replaces it */
.tb-ai__capped { display: flex; align-items: flex-start; gap: var(--space-2); padding: var(--space-3); background: var(--color-surface-sunken); border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-md); font-size: var(--text-xs); color: var(--text-muted); line-height: var(--leading-snug); }
.tb-ai__capped svg { width: 15px; height: 15px; color: var(--text-faint); flex: none; margin-top: 1px; }
.tb-ai__capped b { color: var(--text-strong); font-weight: var(--fw-semibold); }

/* offline / error row */
.tb-ai__error { display: flex; align-items: center; gap: var(--space-2); align-self: stretch; padding: var(--space-2) var(--space-3); background: var(--danger-soft); border: var(--border-width) solid color-mix(in srgb, var(--danger) 22%, transparent); border-radius: var(--radius-md); font-size: var(--text-xs); color: var(--danger); }
.tb-ai__error svg { width: 14px; height: 14px; flex: none; }

/* ---- Launcher: a spark segment appended to the PageToc pill. The ONLY way
   in — the assistant is pill-only; no per-paragraph or under-question triggers.
   The user opens it and asks exactly what they don't understand. ---- */
.tb-pagetoc__ask {
  display: grid; place-items: center; width: 38px; flex: none;
  background: transparent; border: none; border-left: var(--border-width) solid var(--border-soft);
  color: var(--accent-text); cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard);
}
.tb-pagetoc__ask:hover { background: var(--accent-soft); }
.tb-pagetoc__ask svg { width: 15px; height: 15px; }

/* ---- Exam verdict — AI checks a Réponse libre / Code·sortie ----
   Slots into .tb-quiz__solution's place. Lists what's right and what's
   missing, then a verdict. Replaces blind self-grading. ---- */
.tb-quiz__verdict { margin-top: var(--space-3); border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-md); overflow: hidden; }
.tb-quiz__verdict-head { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); background: var(--color-surface-sunken); border-bottom: var(--border-width) solid var(--border-soft); }
.tb-quiz__verdict-head .tb-ai__head-sp { flex: 1; }
.tb-quiz__verdict-flag { font-family: var(--font-ui); font-size: var(--text-2xs); font-weight: var(--fw-semibold); text-transform: uppercase; letter-spacing: var(--tracking-caps); display: inline-flex; align-items: center; gap: var(--space-1); }
.tb-quiz__verdict--ok .tb-quiz__verdict-flag { color: var(--positive); }
.tb-quiz__verdict--partial .tb-quiz__verdict-flag { color: var(--warning); }
.tb-quiz__verdict--no .tb-quiz__verdict-flag { color: var(--danger); }
.tb-quiz__verdict-body { padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.tb-quiz__verdict-line { display: flex; gap: var(--space-2); font-size: var(--text-sm); line-height: var(--leading-snug); }
.tb-quiz__verdict-line svg { width: 15px; height: 15px; flex: none; margin-top: 2px; }
.tb-quiz__verdict-line--ok svg { color: var(--positive); }
.tb-quiz__verdict-line--miss svg { color: var(--warning); }
.tb-quiz__verdict-line b { color: var(--text-strong); font-weight: var(--fw-semibold); }
.tb-quiz__verdict-line span { color: var(--text-body); }

/* ---- Backlog — the SAVED gaps (separate from the ephemeral chat) ---- */
.tb-backlog { list-style: none; margin: 0; padding: 0; border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-md); overflow: hidden; }
.tb-backlog__item { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: var(--border-width) solid var(--border-soft); }
.tb-backlog__item:last-child { border-bottom: none; }
.tb-backlog__where { font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--accent-text); background: var(--accent-soft); border: var(--border-width) solid var(--accent-border); border-radius: var(--radius-xs); padding: 2px 6px; flex: none; margin-top: 1px; white-space: nowrap; }
.tb-backlog__q { flex: 1 1 auto; min-width: 0; font-size: var(--text-sm); color: var(--text-body); line-height: var(--leading-snug); }
.tb-backlog__when { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); flex: none; white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  .tb-ai__thinking span { animation: none; opacity: .6; }
}

/* Local delta (2026-07-16, study): the DS block above has no ≤720px override for
   the panel itself, so it would overflow a phone viewport. Spec §5.3 requires the
   panel to span with insets on mobile. Flagged to design; remove if the DS adopts it. */
@media (max-width: 720px) {
  .tb-ai--floating { left: var(--space-4); right: var(--space-4); width: auto; }
}

/* ================================================================
   Console patterns (2026-07-04) — generic vocabulary for dashboards
   & app surfaces (heures console, study private home, future clients).
   ================================================================ */

/* ---- Stat tile / KPI — the dashboard number ---- */
.tb-stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--space-3); }
.tb-stat {
  background: var(--color-surface);
  border: var(--border-width) solid var(--border-soft);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  display: flex; flex-direction: column; gap: var(--space-2);
  min-width: 0;
}
.tb-stat__label { font-size: var(--text-2xs); font-weight: var(--fw-semibold); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-muted); }
.tb-stat__value-row { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.tb-stat__value { font-size: var(--text-2xl); font-weight: var(--fw-semibold); color: var(--text-strong); line-height: var(--leading-tight); letter-spacing: var(--tracking-tight); font-variant-numeric: tabular-nums; }
.tb-stat__unit { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-muted); }
.tb-stat__delta { font-size: var(--text-xs); font-weight: var(--fw-medium); font-variant-numeric: tabular-nums; }
.tb-stat__delta--positive { color: var(--positive); }
.tb-stat__delta--danger { color: var(--danger); }
.tb-stat__delta--neutral { color: var(--text-muted); }
.tb-stat__hint { font-size: var(--text-xs); color: var(--text-faint); }
.tb-stat__meter { position: relative; height: 4px; border-radius: var(--radius-full); background: var(--viz-track); margin-top: var(--space-1); }
.tb-stat__meter-fill { position: absolute; top: 0; bottom: 0; left: 0; border-radius: inherit; background: var(--viz-fill); }
.tb-stat__meter-mark { position: absolute; top: -3px; bottom: -3px; width: 2px; border-radius: 1px; background: var(--viz-threshold); }
.tb-stat__chart { margin-top: var(--space-1); }

/* ---- Chart chrome (SVG charts use the --viz-* tokens; these classes
        style the HTML around them: legend + tooltip) ---- */
.tb-viz-legend { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); font-size: var(--text-xs); color: var(--viz-label); }
.tb-viz-legend__item { display: inline-flex; align-items: center; gap: var(--space-2); }
.tb-viz-legend__swatch { width: 10px; height: 10px; border-radius: var(--radius-xs); flex: none; }
.tb-viz-tooltip {
  background: var(--viz-tooltip-bg); color: var(--viz-tooltip-fg);
  border: var(--border-width) solid var(--viz-tooltip-border);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs); line-height: var(--leading-snug);
  min-width: 120px;
}
.tb-viz-tooltip__title { font-weight: var(--fw-semibold); color: var(--text-strong); margin-bottom: 2px; }
.tb-viz-tooltip__row { display: flex; justify-content: space-between; gap: var(--space-3); }
.tb-viz-tooltip__row b { font-family: var(--font-mono); font-weight: var(--fw-medium); font-variant-numeric: tabular-nums; color: var(--text-strong); }

/* ---- Drawer / slide-over — right-anchored detail panel ---- */
.tb-drawer { position: fixed; inset: 0; z-index: var(--z-modal); display: flex; justify-content: flex-end; }
.tb-drawer__backdrop { position: absolute; inset: 0; background: var(--scrim); animation: tb-drawer-fade var(--dur-base) var(--ease-standard); }
.tb-drawer__panel {
  position: relative;
  width: min(480px, 100%); height: 100%;
  background: var(--color-surface);
  border-left: var(--border-width) solid var(--border-soft);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  animation: tb-drawer-in var(--dur-slow) var(--ease-out);
}
.tb-drawer--sm .tb-drawer__panel { width: min(360px, 100%); }
.tb-drawer--lg .tb-drawer__panel { width: min(640px, 100%); }
.tb-drawer__head { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-bottom: var(--border-width) solid var(--border-soft); flex: none; }
.tb-drawer__titles { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tb-drawer__eyebrow { font-size: var(--text-2xs); font-weight: var(--fw-semibold); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--accent-text); }
.tb-drawer__title { margin: 0; font-size: var(--text-md); font-weight: var(--fw-semibold); color: var(--text-strong); line-height: var(--leading-snug); letter-spacing: var(--tracking-tight); }
.tb-drawer__body { flex: 1 1 auto; overflow-y: auto; padding: var(--space-5); }
.tb-drawer__foot { flex: none; display: flex; justify-content: flex-end; gap: var(--space-2); padding: var(--space-3) var(--space-5); border-top: var(--border-width) solid var(--border-soft); }
@keyframes tb-drawer-in { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes tb-drawer-fade { from { opacity: 0; } to { opacity: 1; } }
@media (max-width: 640px) {
  .tb-drawer__panel, .tb-drawer--sm .tb-drawer__panel, .tb-drawer--lg .tb-drawer__panel { width: 100%; border-left: none; }
}

/* ================================================================
   Console patterns — lot 2 (2026-07-04): chips canon, list rows +
   « … » menu, doc-cards, empty states, search + filter bar.
   Generic by contract: heures, study privé, futurs clients.
   ================================================================ */

/* ---- Status chips: ONE canon, carried by .tb-badge (no fork).
   Rule: tint = where the decision/money stands · dot = "waiting on
   someone". See the « Chips & statuts » card.
     brouillon → neutral          envoyé     → accent + dot
     accepté   → positive         refusé     → danger
     payée     → positive         en attente → warning + dot
     en retard → danger + dot     en pause   → info
     annulée   → neutral + --struck                                  */
.tb-badge--struck { text-decoration: line-through; text-decoration-color: currentColor; }

/* ---- Actionable list row (.tb-rows > .tb-row) ---- */
.tb-rows { list-style: none; margin: 0; padding: 0; background: var(--color-surface); border: var(--hairline); border-radius: var(--radius-md); }
.tb-row { position: relative; display: flex; align-items: center; gap: var(--space-4); padding: var(--space-3) var(--space-4); border-bottom: var(--hairline); }
.tb-row:last-child { border-bottom: none; }
.tb-rows > .tb-row:first-child { border-top-left-radius: inherit; border-top-right-radius: inherit; }
.tb-rows > .tb-row:last-child { border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; }
.tb-row--clickable { cursor: pointer; transition: background var(--dur-fast) var(--ease-standard); }
.tb-row--clickable:hover { background: var(--color-surface-hover); }
.tb-row__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tb-row__title { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tb-row__meta { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--text-muted); min-width: 0; flex-wrap: wrap; }
.tb-row__meta .tb-badge { flex: none; }
.tb-row__end { display: flex; align-items: center; gap: var(--space-3); flex: none; }
.tb-row__num { font-family: var(--font-mono); font-size: var(--text-sm); font-variant-numeric: tabular-nums; color: var(--text-strong); }
/* Row states — the chip names the status, the row carries the tone */
.tb-row--dimmed { opacity: .55; }
.tb-row--dimmed .tb-row__title { text-decoration: line-through; text-decoration-color: var(--text-faint); }
.tb-row--hold { background: var(--color-surface-sunken); }
.tb-row--paid .tb-row__num { color: var(--text-muted); }

/* ---- « … » overflow menu ---- */
.tb-menuwrap { position: relative; display: inline-flex; }
.tb-menu {
  position: absolute; top: calc(100% + var(--space-1)); right: 0; z-index: var(--z-overlay);
  min-width: 190px; background: var(--color-surface); border: var(--rule);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: var(--space-1);
  animation: tb-menu-in var(--dur-fast) var(--ease-out);
}
.tb-menu--left { right: auto; left: 0; }
@keyframes tb-menu-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.tb-menu__item {
  display: flex; align-items: center; gap: var(--space-2); width: 100%; text-align: left;
  font-family: var(--font-ui); font-size: var(--text-sm); color: var(--text-body);
  background: none; border: none; border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3); cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.tb-menu__item:hover { background: var(--color-surface-hover); color: var(--text-strong); }
.tb-menu__item:disabled { color: var(--text-faint); cursor: not-allowed; }
.tb-menu__item svg { width: 15px; height: 15px; flex: none; color: var(--text-faint); }
.tb-menu__item:hover svg { color: currentColor; }
.tb-menu__item--danger { color: var(--danger); }
.tb-menu__item--danger svg { color: var(--danger); }
.tb-menu__item--danger:hover { background: var(--danger-soft); color: var(--danger); }
.tb-menu__sep { height: 1px; background: var(--border-soft); margin: var(--space-1) var(--space-2); }

/* ---- Doc-card — a document as a card (kind · title · date · status) ---- */
.tb-doccard-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--space-3); }
.tb-doccard {
  display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4);
  background: var(--color-surface); border: var(--hairline); border-radius: var(--radius-md);
  text-decoration: none; color: inherit;
  transition: border-color var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard);
}
button.tb-doccard { font: inherit; text-align: left; cursor: pointer; width: 100%; }
a.tb-doccard:hover, button.tb-doccard:hover { border-color: var(--accent-border); box-shadow: var(--shadow-sm); text-decoration: none; }
a.tb-doccard:focus-visible, button.tb-doccard:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.tb-doccard__kind {
  align-self: flex-start; font-family: var(--font-mono); font-size: var(--text-2xs);
  text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-muted);
  border: var(--hairline); border-radius: var(--radius-xs); padding: 1px 6px;
}
.tb-doccard__title {
  font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-strong);
  line-height: var(--leading-snug); letter-spacing: var(--tracking-tight);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.tb-doccard__foot { margin-top: auto; padding-top: var(--space-2); display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.tb-doccard__date { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); font-variant-numeric: tabular-nums; }

/* ---- Empty state ---- */
.tb-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-1); text-align: center; padding: var(--space-10) var(--space-6);
  border: 1px dashed var(--border); border-radius: var(--radius-md); color: var(--text-muted);
}
.tb-empty--bare { border: none; padding: var(--space-8) var(--space-4); }
.tb-empty__icon { width: 22px; height: 22px; color: var(--text-faint); margin-bottom: var(--space-2); }
.tb-empty__icon svg { width: 100%; height: 100%; display: block; }
.tb-empty__title { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-body); }
.tb-empty__hint { font-size: var(--text-xs); color: var(--text-faint); max-width: 42ch; line-height: var(--leading-snug); }
.tb-empty__action { margin-top: var(--space-3); }

/* ---- Search + filter/scope bar ---- */
.tb-filterbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.tb-filterbar__search { position: relative; flex: 1 1 220px; min-width: 180px; max-width: 360px; }
.tb-filterbar__search > svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); width: 15px; height: 15px; color: var(--text-faint); pointer-events: none; }
.tb-filterbar__search .tb-field { padding-left: 32px; }
.tb-filterbar__group { display: flex; align-items: center; gap: var(--space-1); }
.tb-filterbar__sep { width: 1px; height: 20px; background: var(--border-soft); margin: 0 var(--space-1); flex: none; }
/* results treatment: mono count here; matched text inside results keeps
   the existing inline .tb-mark highlight */
.tb-filterbar__count { margin-left: auto; font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Filter/scope chip — INTERACTIVE (≠ .tb-badge, which labels a status) */
.tb-chip {
  display: inline-flex; align-items: center; gap: var(--space-1); height: 28px; padding: 0 var(--space-3);
  font-family: var(--font-ui); font-size: var(--text-xs); font-weight: var(--fw-medium);
  color: var(--text-muted); background: var(--color-surface); border: var(--rule);
  border-radius: var(--radius-full); cursor: pointer; white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.tb-chip:hover { color: var(--text-body); border-color: var(--border-strong); }
.tb-chip:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.tb-chip.is-active { color: var(--accent-text); background: var(--accent-soft); border-color: var(--accent-border); }
.tb-chip__count { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); }
.tb-chip.is-active .tb-chip__count { color: inherit; opacity: .75; }
.tb-chip__x { display: inline-grid; place-items: center; width: 14px; height: 14px; margin-right: -4px; border-radius: 50%; color: inherit; opacity: .7; }
.tb-chip__x svg { width: 10px; height: 10px; display: block; }
.tb-chip.is-active:hover .tb-chip__x { opacity: 1; background: color-mix(in srgb, var(--accent) 15%, transparent); }

/* ================================================================
   Console primitives — lot 4 (2026-07-05): panel, formulaires CRUD,
   confirmation destructive, feedback de sauvegarde, mobile, dragover.
   Réponse à DESIGN-REQUEST-2026-07-05-console-primitives.
   ================================================================ */

/* ---- Panel — the framed content/chart panel (promoted from the
   dataviz card demo; charts, tables and lists sit inside one) ---- */
.tb-panel {
  background: var(--color-surface); border: var(--border-width) solid var(--border-soft);
  border-radius: var(--radius-md); padding: var(--space-4) var(--space-5);
  display: flex; flex-direction: column; gap: var(--space-3); min-width: 0;
}
.tb-panel__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.tb-panel__title { margin: 0; font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--text-strong); }

/* ---- Chart plot area — relative wrapper the HTML tooltip anchors to ---- */
.tb-viz-plot { position: relative; min-width: 0; }
.tb-viz-plot .tb-viz-tooltip {
  position: absolute; top: 0; transform: translate(-50%, calc(-100% - 6px));
  pointer-events: none; z-index: var(--z-overlay); white-space: nowrap;
}

/* ---- Form pattern — labelled field + grouped section (console CRUD).
   Canon: console forms save EXPLICITLY (Enregistrer in the Drawer foot
   + SaveStatus), never silently on blur. ---- */
.tb-form { display: flex; flex-direction: column; gap: var(--space-4); }
.tb-formsection { border: var(--border-width) solid var(--border-soft); border-radius: var(--radius-md); background: var(--color-surface); }
.tb-formsection__head {
  display: flex; align-items: baseline; gap: var(--space-2);
  padding: var(--space-3) var(--space-4); border-bottom: var(--border-width) solid var(--border-soft);
  background: var(--color-surface-sunken); border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.tb-formsection__title {
  margin: 0; font-size: var(--text-2xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-muted);
}
.tb-formsection__hint { font-size: var(--text-xs); color: var(--text-faint); }
.tb-formsection__body { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); }
.tb-formgrid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.tb-formgrid > .is-full { grid-column: 1 / -1; }
@media (max-width: 560px) { .tb-formgrid { grid-template-columns: minmax(0, 1fr); } }

.tb-formfield { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.tb-formfield__label { font-size: var(--text-xs); font-weight: var(--fw-medium); color: var(--text-body); }
.tb-formfield__req { color: var(--danger); margin-left: 2px; }
.tb-formfield__help { font-size: var(--text-xs); color: var(--text-faint); line-height: var(--leading-snug); }
.tb-formfield__error { font-size: var(--text-xs); color: var(--danger); line-height: var(--leading-snug); }
.tb-formfield--invalid .tb-field { border-color: var(--danger); }
.tb-formfield--invalid .tb-field:focus { border-color: var(--danger); box-shadow: 0 0 0 3px var(--danger-soft); }

/* ---- Destructive confirmation — THE canonical pattern.
   Centered dialog on --scrim: title + one-line consequence +
   Annuler / Confirmer (danger). Never window.confirm. ---- */
.tb-confirm { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; place-items: center; padding: var(--space-6); }
.tb-confirm__backdrop { position: absolute; inset: 0; background: var(--scrim); animation: tb-drawer-fade var(--dur-base) var(--ease-standard); }
.tb-confirm__panel {
  position: relative; width: min(420px, 100%);
  background: var(--color-surface); border: var(--border-width) solid var(--border-soft);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
  padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2);
  animation: tb-confirm-in var(--dur-base) var(--ease-out);
}
@keyframes tb-confirm-in { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
.tb-confirm__title { margin: 0; font-size: var(--text-md); font-weight: var(--fw-semibold); color: var(--text-strong); letter-spacing: var(--tracking-tight); line-height: var(--leading-snug); }
.tb-confirm__text { font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-snug); }
.tb-confirm__text b { color: var(--text-strong); font-weight: var(--fw-semibold); }
.tb-confirm__actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-3); }

/* ---- Save feedback — « Enregistré ✓ » inline, usable IN a Drawer foot
   (a page banner hides behind the scrim; this never does). ---- */
.tb-save {
  display: inline-flex; align-items: center; gap: var(--space-1);
  font-family: var(--font-ui); font-size: var(--text-xs); color: var(--text-faint);
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.tb-save svg { width: 13px; height: 13px; flex: none; }
.tb-save--saved { color: var(--positive); }
.tb-save--error { color: var(--danger); }
.tb-save.is-leaving { opacity: 0; }
.tb-save__retry {
  font: inherit; color: inherit; background: none; border: none; cursor: pointer;
  text-decoration: underline; text-underline-offset: 2px; padding: 0; margin-left: var(--space-1);
}

/* ---- EmptyState as a drop-zone — dragover state ---- */
.tb-empty.is-dragover { border-color: var(--accent); background: var(--accent-soft); }
.tb-empty.is-dragover .tb-empty__icon, .tb-empty.is-dragover .tb-empty__title { color: var(--accent-text); }

/* ---- Mobile canon (shared, so no app re-invents it) ----
   Rows fold into a stack; the filter search takes the full line. */
@media (max-width: 560px) {
  .tb-row { flex-wrap: wrap; row-gap: var(--space-2); }
  .tb-row__main { flex: 1 1 100%; }
  .tb-row__end { margin-left: auto; }
  .tb-filterbar__search { max-width: none; }
}
/* Touch targets ≥44px when the primary input is coarse. */
@media (pointer: coarse) {
  .tb-iconbtn { width: 44px; height: 44px; }
  .tb-btn, .tb-btn--sm, .tb-btn--lg { min-height: 44px; }
  .tb-chip { min-height: 44px; }
  .tb-menu__item { padding-top: var(--space-3); padding-bottom: var(--space-3); }
  .tb-seg__btn { min-height: 40px; }
}

/* ================================================================
   ADDRESS BAR — la couture partagée des cinq adresses (2026-08-04)
   Graduated from cards/adresses/_adresses.css (lot « Cinq adresses,
   un public chacune », Q4). ONE 52px rail, identical on
   tbosshart.dev · study · portal · heures · app. It is a SEAM, not a
   shell: the five addresses share this strip and nothing else — no
   common navigation, no common template (they have different jobs).
   Fixed: height (--nav-height), the emerald prompt mark at 16px, the
   section name in display semibold, the address in mono prefixed "/",
   the bottom hairline, the surface background.
   Variable: the section name, the address, and the right slot —
   identity alone on the public root, connected e-mail + « Quitter »
   behind Access, nav links on the console.
   On the console (heures) this IS .tb-nav's job; use whichever the
   surface already carries, never both.
   ================================================================ */
.tb-addrbar { display: flex; align-items: center; gap: var(--space-3); height: var(--nav-height); padding: 0 var(--page-gutter); border-bottom: var(--hairline); background: var(--color-surface); }
.tb-addrbar__mark { width: 16px; height: 16px; color: var(--accent); flex: none; }
.tb-addrbar__mark svg { display: block; width: 100%; height: 100%; }
.tb-addrbar__name { font-family: var(--font-display); font-weight: var(--fw-semibold); font-size: var(--text-sm); letter-spacing: var(--tracking-tight); color: var(--text-strong); white-space: nowrap; }
.tb-addrbar__addr { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); white-space: nowrap; }
.tb-addrbar__sp { flex: 1 1 auto; }
.tb-addrbar__end { display: flex; align-items: center; gap: var(--space-3); font-size: var(--text-xs); color: var(--text-muted); min-width: 0; }
.tb-addrbar__who { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tb-addrbar__end a { color: var(--text-muted); text-decoration: none; }
.tb-addrbar__end a:hover { color: var(--accent-text); }
/* Sticky is opt-in: the portal and the launcher keep it in view, the
   public root lets it scroll away with the page. */
.tb-addrbar--sticky { position: sticky; top: 0; z-index: var(--z-sticky); }
/* On the phone only the gutter tightens: the address is the whole point
   of the seam, so it never drops out. */
@media (max-width: 40rem) {
  .tb-addrbar { padding: 0 var(--space-4); gap: var(--space-2); }
}
