/* TTA admin portal — translated from design-system ui_kits/admin-portal */
@import url("tokens/fonts.30bbb7e91523.css");
@import url("tokens/colors.3e1cc1a45529.css");
@import url("tokens/typography.9a217134c680.css");
@import url("tokens/spacing.ffe46b1b234a.css");
@import url("tokens/radius.2c2377cec9d4.css");
@import url("tokens/elevation.93ad908d6f21.css");
@import url("tokens/motion.3a4648139f93.css");
@import url("tokens/base.7218a712225e.css");
@import url("icons/icons.9fb12a4e393c.css");

/* Anything here that sets display, and nearly everything does, outranks the
   browser's own [hidden] rule, so hiding something in JS left it on screen.
   Said once, instead of patching it per component. */
[hidden] { display: none !important; }

/* ── Frame: forest-900 side rail + white content (SideNav.jsx spec) ── */
.shell { display: grid; grid-template-columns: var(--sidenav-width) 1fr; min-height: 100vh; background: var(--surface-page); }
/* The footer owns the bottom padding, so it sits flush on the rail's edge
   and bleeds the full width behind it (AdminShell passes paddingBottom 0). */
.sidenav { background: var(--forest-900); color: var(--tta-white); display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh; padding: 26px 14px 0; }
.sidenav-logo { padding: 0 8px 26px; display: flex; align-items: center; gap: 9px; }
.sidenav-logo .monogram { height: 26px; width: 26px; display: block; }
.sidenav-logo .wordmark { font: var(--weight-bold) 14px/1.15 var(--font-display); letter-spacing: var(--tracking-heading); color: var(--tta-white); }
.sidenav nav { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 3px; }
.nav-section { font: var(--type-micro); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: rgba(255,255,255,.35); padding: 18px 11px 7px; }
.sidenav a.nav-item { display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 0 12px; border-radius: var(--radius-button); color: rgba(255,255,255,.74); font: var(--weight-medium) var(--size-body)/1 var(--font-body); transition: var(--transition-interactive); }
.sidenav a.nav-item:hover { background: var(--overlay-hover-dark); color: var(--tta-white); }
.sidenav a.nav-item.active { background: var(--tta-green); color: var(--tta-black); font-weight: var(--weight-semibold); }
.nav-item .badge-count { margin-left: auto; min-width: 21px; height: 20px; padding: 0 6px; display: grid; place-items: center; background: var(--tta-green); color: var(--tta-black); border-radius: var(--radius-pill); font: var(--weight-bold) 11px/1 var(--font-body); font-variant-numeric: tabular-nums; }
.nav-item.active .badge-count { background: rgba(0,0,0,.14); }
/* AdminShell's footer: pinned to the bottom of the rail, full bleed over it,
   a row of round controls above the person. It used to be one flex row with
   the notifications item, the avatar, the name and two buttons all competing
   for 225px, so the name spilled out of the rail. */
.sidenav-footer {
  position: sticky; bottom: 0; z-index: 1;
  margin: 0 -14px; padding: 10px 14px 16px;
  background: var(--forest-900); border-top: 1px solid var(--border-on-dark);
  display: grid; gap: 10px;
}
.footer-tools { display: flex; align-items: center; gap: 6px; padding: 0 2px; }
.footer-tools .tool {
  position: relative; width: 34px; height: 34px; flex: 0 0 auto;
  border: 0; border-radius: var(--radius-pill); padding: 0; cursor: pointer;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .1); color: var(--tta-white);
  transition: var(--transition-interactive);
}
.footer-tools .tool:hover { background: rgba(255, 255, 255, .2); }
.footer-tools .tool.on { background: var(--tta-green); color: var(--tta-black); }
.footer-tools .tool-count {
  position: absolute; top: -3px; right: -3px;
  min-width: 17px; height: 17px; padding: 0 4px; box-sizing: border-box;
  border-radius: var(--radius-pill); background: var(--tta-green); color: var(--tta-black);
  font: var(--weight-bold) 10px/17px var(--font-body); font-variant-numeric: tabular-nums;
  text-align: center;
}
.footer-tools .tool.on .tool-count { background: var(--tta-black); color: var(--tta-green); }
.footer-who { display: flex; align-items: center; gap: 11px; padding: 0 2px; }
.sidenav-footer .avatar { width: 34px; height: 34px; border-radius: var(--radius-pill); background: var(--forest-500); color: var(--tta-white); display: grid; place-items: center; font: var(--weight-semibold) 12px/1 var(--font-display); flex: 0 0 auto; }
.sidenav-footer .who { display: grid; gap: 1px; min-width: 0; flex: 1; }
/* A long name shortens; it never pushes the rail open. */
.sidenav-footer .who .name { font: var(--weight-semibold) var(--size-body-s)/1.25 var(--font-body); color: var(--tta-white); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidenav-footer .who .role { font: var(--type-body-s); color: rgba(255,255,255,.6); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }


/* ── The bell's popover (NotifyBell.jsx) ─────────────────────────────── */
/* Anchored beside the rail rather than inside it, so the rail never clips
   it, and pinned to the bottom the way the bell's own button sits. */
.bell-pop {
  position: fixed; z-index: 60;
  left: calc(var(--sidenav-width) + 12px); bottom: 16px;
  width: min(380px, calc(100vw - var(--sidenav-width) - 24px));
  max-height: min(600px, calc(100vh - 40px));
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
  background: var(--surface-card); border-radius: var(--radius-card);
  border: 1px solid var(--border-subtle);
  box-shadow: 0 20px 48px -20px rgba(0, 0, 0, .45);
  overflow: hidden;
}
.bell-head { display: flex; align-items: center; gap: 10px; padding: 14px 16px 6px; }
.bell-title { flex: 1; font: var(--weight-semibold) var(--size-h4)/1.2 var(--font-display); }
.bell-list { overflow-y: auto; padding: 0 6px 8px; display: grid; align-content: start; }
.bell-group { font: var(--type-label); color: var(--text-muted); padding: 12px 10px 6px; }
.bell-row {
  width: 100%; display: grid; grid-template-columns: 10px 1fr; gap: 10px;
  padding: 10px; border: 0; border-radius: var(--radius-tile);
  background: transparent; cursor: pointer; text-align: left;
}
.bell-row.unread { background: var(--surface-sunken); }
.bell-row:hover { background: var(--overlay-hover-light); }
.bell-dot { width: 8px; height: 8px; margin-top: 6px; border-radius: var(--radius-pill); background: var(--tta-green); }
.bell-dot.read { background: transparent; }
.bell-dot.stop { background: var(--signal-stop); }
.bell-text { display: grid; gap: 3px; min-width: 0; }
.bell-line { display: flex; gap: 8px; align-items: baseline; }
.bell-name { flex: 1; font: var(--weight-semibold) var(--size-body-s)/1.3 var(--font-body); }
.bell-when { font: var(--type-body-s); color: var(--text-muted); white-space: nowrap; }
.bell-body { font: var(--type-body-s); color: var(--text-secondary); }
.bell-empty { display: block; padding: 16px; font: var(--type-body-s); color: var(--text-muted); }
.bell-all { padding: 12px 16px; border-top: 1px solid var(--border-subtle); font: var(--type-body-s); }

/* ── Content ── */
.content { min-width: 0; }
.toolbar { position: sticky; top: 0; z-index: 5; background: var(--surface-page); display: flex; align-items: flex-end; gap: 20px; padding: 24px var(--gutter-web); border-bottom: 1px solid var(--border-subtle); }
.toolbar .titles { flex: 1; min-width: 0; display: grid; gap: 5px; }
/* readme casing table: eyebrows are one of the two places caps survive. */
/* Toolbar.jsx renders this as a plain line, not an eyebrow: a count, a date,
   a context. The caps treatment belongs to card eyebrows and badges. */
.toolbar .eyebrow { font: var(--type-body-s); color: var(--text-secondary); }
.toolbar h1 { font: var(--type-display-l); letter-spacing: var(--tracking-display); }
.page { padding: var(--gutter-web); max-width: var(--content-max); display: grid; gap: var(--stack-section); align-content: start; }

/* ── Buttons ── */
/* Button.jsx: display face, 48px at size m, 1px border so secondary reads as
   a button and not a card. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 9px; border: 1px solid transparent; border-radius: var(--radius-button); font: var(--weight-semibold) var(--size-body)/1 var(--font-display); letter-spacing: -0.005em; padding: 0 20px; min-height: 48px; cursor: pointer; transition: var(--transition-interactive); text-decoration: none; white-space: nowrap; }
.btn:active { transform: scale(var(--press-scale)); }
/* interactions.css: a press darkens the fill as well as scaling. */
.btn-primary:active { background: var(--accent-press); }
.btn-dark:active { background: var(--forest-800); }
.btn-black:active { background: var(--grey-700); }
.btn-secondary:active { background: var(--grey-100); }
.row:active { background: var(--grey-100); }
.btn-primary { background: var(--tta-green); color: var(--text-on-accent); box-shadow: var(--shadow-accent); }
.btn-primary:hover { background: var(--accent-hover); color: var(--text-on-accent); }
.btn-secondary { background: var(--tta-white); color: var(--text-primary); border-color: var(--border-default); }
.btn-secondary:hover { background: var(--grey-050); border-color: var(--grey-400); color: var(--text-primary); }
.btn-dark { background: var(--surface-deep); color: var(--tta-white); }
.btn-dark:hover { background: var(--forest-500); color: var(--tta-white); }
.btn-ghost { background: transparent; color: var(--text-secondary); }
.btn-ghost:hover { background: var(--overlay-hover-light); color: var(--text-primary); }
/* Button.d.ts: onDark and glass are for forest, black and video surfaces. */
.btn-on-dark { background: rgba(255,255,255,.14); color: var(--tta-white); }
.btn-on-dark:hover { background: var(--overlay-hover-dark); color: var(--tta-white); }
.btn-glass { background: rgba(255,255,255,.18); color: var(--tta-white); backdrop-filter: var(--blur-glass, blur(14px)); -webkit-backdrop-filter: var(--blur-glass, blur(14px)); }
.btn-glass:hover { background: rgba(255,255,255,.24); color: var(--tta-white); }
/* Fully round, for chips and floating actions. */
.btn-pill { border-radius: var(--radius-pill); }
.btn-danger { background: var(--signal-stop); color: var(--tta-white); }
.btn-danger:hover { filter: brightness(1.08); }
/* A destructive row action reads as destructive: red text, not body colour.
   The design's quality pass found these rendering as ordinary options. */
.btn-danger-ghost { background: transparent; color: var(--signal-stop); }
.btn-danger-ghost:hover { background: var(--signal-stop-soft, rgba(217, 65, 47, .08)); color: var(--signal-stop); }
/* The design separates forest "dark" from pure "black". */
.btn-black { background: var(--tta-black); color: var(--tta-white); }
.btn-black:hover { background: var(--grey-800); color: var(--tta-white); }
.btn-s { gap: 7px; padding: 0 15px; min-height: 38px; font-size: var(--size-body-s); border-radius: var(--radius-button-small); }
.btn-l { gap: 10px; padding: 0 26px; min-height: 56px; font-size: var(--size-body-l); }
.btn[disabled] { opacity: .38; box-shadow: none; pointer-events: none; }

/* ── Cards & tiles ── */
.card { background: var(--surface-card); border-radius: var(--radius-card); box-shadow: var(--shadow-card); padding: var(--card-pad-web); }
.card.pad-list { padding: 6px; }
.tile { border-radius: var(--radius-tile); padding: var(--tile-pad) 18px; display: grid; gap: 6px; align-content: start; background: var(--surface-sunken); }
.tile.dark { background: var(--tta-black); color: var(--tta-white); }
.tile.accent { background: var(--tta-green); color: var(--tta-black); }
.tile.deep { background: var(--forest-700); color: var(--tta-white); }
/* MetricTile.jsx and StatBoxes.jsx both label a metric in plain body-s. The
   caps treatment is for eyebrows and badges. */
.tile .label { font: var(--type-body-s); opacity: .72; }
.tile .metric { font: var(--weight-bold) var(--size-metric-l)/1 var(--font-numeric); font-variant-numeric: tabular-nums; letter-spacing: var(--tracking-display); }
.tile .metric .unit { font: var(--weight-medium) var(--size-body-s)/1 var(--font-body); opacity: .6; margin-left: 3px; }
.tile .hint { font: var(--type-body-s); opacity: .65; }
/* A narrow column of choices beside the thing they choose: documents, team
   profiles, an evaluation's sections. Was an inline style on four pages,
   which no media query could reach. */
/* Rows that are a table in everything but markup. One shape per kind, so a
   phone can stack them the way it stacks a real one. */
.grid-row { display: grid; gap: 12px; align-items: center; padding: 12px 14px; font: var(--type-body-s); }
.grid-row[data-ruled] { border-top: 1px solid var(--border-subtle); }
.grid-row-head { font: var(--type-label); color: var(--text-muted); padding: 10px 14px; }
.grid-row-4 { grid-template-columns: 1.2fr 1fr 1.4fr 140px; }
.grid-row-legs { grid-template-columns: 110px 120px 1fr 20px 1fr auto; }
.grid-row-cost { grid-template-columns: 1.6fr 90px 1.3fr 1fr 1fr; }
.split-aside { display: grid; grid-template-columns: minmax(180px, 220px) minmax(0, 1fr); gap: 20px; align-items: start; }
/* The builder: the work on the left, the panel that acts on it on the right. */
.split-main { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 24px; align-items: start; }
.tile-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; }

/* ── Section headers ── */
.section { display: grid; gap: 12px; }
.section-head { display: flex; align-items: baseline; gap: 12px; }
.section-head h2 { font: var(--type-h2); letter-spacing: var(--tracking-heading); flex: 1; }
.section-head a { font: var(--weight-semibold) var(--size-body-s)/1 var(--font-body); }

/* ── Badges / status pills ── */
.pill { display: inline-flex; align-items: center; gap: 6px; height: 28px; border-radius: var(--radius-badge); font: var(--weight-semibold) var(--size-micro)/1 var(--font-body); text-transform: uppercase; letter-spacing: var(--tracking-caps); padding: 0 12px; white-space: nowrap; }
.pill-s { height: 22px; padding: 0 9px; font-size: 10px; }
.pill-neutral { background: var(--grey-100); color: var(--grey-600); }
.pill-outline { background: transparent; box-shadow: inset 0 0 0 1px var(--border-subtle); color: var(--text-secondary); }
.pill-accent { background: var(--tta-green); color: var(--tta-black); }
.pill-accent-soft { background: var(--green-050); color: var(--green-700); }
.pill-hold { background: #FDF3E4; color: #8A5A12; }
.pill-stop { background: #FCEBE9; color: #A32A1D; }

/* Badge.jsx also carries two tones for dark surfaces, and a sentence-case
   variant for the rare pill that holds a name or a count. */
.pill-on-dark { background: rgba(255,255,255,.12); color: var(--tta-white); }
.pill-on-dark-outline { background: transparent; color: rgba(255,255,255,.8); box-shadow: inset 0 0 0 1px rgba(255,255,255,.22); }
.pill-sentence { text-transform: none; letter-spacing: 0; }
.pill-m { height: 28px; padding: 0 12px; }.pill-dark { background: var(--tta-black); color: var(--tta-white); }
.pill-forest { background: var(--forest-700); color: var(--tta-white); }
.pill .dot { width: 6px; height: 6px; border-radius: 999px; background: currentColor; }

/* ── Tables ── */
/* DataTable.jsx: columns keep their width and the table scrolls, rather than
   squeezing text to nothing in a narrow window. One rule for every table, so
   there is a single convention. */
.card:has(> .dt) { overflow-x: auto; }
.card > .dt { min-width: 720px; }
.dt { width: 100%; border-collapse: collapse; }
.dt th { font: var(--type-micro); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-secondary); text-align: left; padding: 14px 20px; background: var(--surface-inset); border-bottom: 1px solid var(--border-subtle); }
.dt td { padding: 16px 20px; border-bottom: 1px solid var(--border-subtle); font: var(--type-body-s); color: var(--text-secondary); vertical-align: middle; }
.dt tr:last-child td { border-bottom: 0; }
.dt tbody tr { transition: var(--transition-interactive); }
.dt tbody tr:hover { background: var(--surface-inset); }
.dt td.strong, .dt td a.strong { font: var(--weight-semibold) var(--size-body)/1.3 var(--font-display); color: var(--text-primary); }
.dt td.num { text-align: right; font-variant-numeric: tabular-nums; }

/* ── Rows (list inside card) ── */
.row { display: flex; align-items: center; gap: 14px; padding: 13px 14px; border-radius: var(--radius-m); transition: var(--transition-interactive); min-height: var(--row-min-height); }
a.row { color: inherit; font-weight: inherit; }
.row:hover { background: var(--surface-inset); }
.row .grow { flex: 1; min-width: 0; display: grid; gap: 2px; }
.row .t { font: var(--weight-semibold) var(--size-body)/1.3 var(--font-display); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .s { font: var(--type-body-s); color: var(--text-secondary); }
/* Avatar.jsx — a pill with the initials. The base class, because it is used
   outside list rows too (trip segments, team profiles, the dashboard). */
.avatar { width: 38px; height: 38px; border-radius: var(--radius-pill); background: var(--forest-100); color: var(--forest-700); display: grid; place-items: center; font: var(--weight-semibold) 13px/1 var(--font-display); flex: 0 0 auto; text-transform: uppercase; }
.row .avatar { width: 38px; height: 38px; border-radius: var(--radius-pill); background: var(--forest-100); color: var(--forest-700); display: grid; place-items: center; font: var(--weight-semibold) 13px/1 var(--font-display); flex: 0 0 auto; }

/* ── Forms ── */
.field { display: grid; gap: 7px; }
/* Input.jsx: the label is sentence case body-s. Caps are for eyebrows and badges. */
.field label { font: var(--type-body-s); color: var(--text-secondary); }
.field input, .field select, .field textarea { width: 100%; min-width: 0; border: 1px solid var(--border-default); border-radius: var(--radius-input); padding: 0 15px; font: var(--weight-medium) var(--size-body)/1 var(--font-body); color: var(--text-primary); background: var(--surface-card); height: 50px; transition: var(--transition-interactive); }
.field select { appearance: none; -webkit-appearance: none; padding-right: 42px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23686868' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 15px center; background-size: 17px; }
.field textarea { height: auto; min-height: 92px; padding: 13px 15px; line-height: 1.55; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: var(--text-muted); font-weight: var(--weight-regular); }
/* Rows line up by their tops, so a message appearing under one field cannot
   drop it out of line with its neighbours. Buttons still sit on the input. */
.filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: start; }
.filters > button, .filters > .btn, .filters > form > button { align-self: flex-end; }
#rows .field input, #rows .field select { width: 100%; min-width: 0; padding: 10px 8px; }
#rows > div { min-width: 0; }
/* A field in a row keeps its size whatever is written under it: with an auto
   basis a long error message became the field's width and shoved every other
   field onto its own line. */
.filters .field { flex: 1 1 160px; min-width: 160px; max-width: 100%; }
/* Select.jsx sizes: s = 42, m = 50, l = 56. A filter row uses the small one,
   the way every Toolbar in the design does. */
.filters .field input, .filters .field select { height: 42px; }
.field-s input, .field-s select { height: 42px; }
.field-l input, .field-l select { height: 56px; }
/* SegmentedControl.jsx: sunken track, the selected segment is a white pill
   with a soft shadow — the same control the app uses. */
.seg { display: inline-flex; background: var(--surface-sunken); border-radius: var(--radius-pill); padding: 4px; gap: 4px; align-self: start; justify-self: start; width: fit-content; }
.seg a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px; border-radius: var(--radius-pill); font: var(--weight-medium) var(--size-body-s)/1 var(--font-body); color: var(--text-secondary); transition: var(--transition-interactive); }
.seg a:hover { color: var(--text-primary); }
.seg-s a { min-height: 36px; padding: 0 14px; }
.seg a.on { background: var(--tta-white); color: var(--text-primary); font-weight: var(--weight-semibold); box-shadow: 0 1px 2px rgba(0,0,0,.06), 0 4px 10px -6px rgba(0,0,0,.2); }
select.inline-select { appearance: none; -webkit-appearance: none; border: 1px solid var(--border-default); border-radius: var(--radius-input); padding: 0 38px 0 14px; font: var(--weight-medium) var(--size-body-s)/1 var(--font-body); background: var(--tta-white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23686868' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 11px center / 15px; cursor: pointer; min-height: 42px; transition: var(--transition-interactive); }
select.inline-select:focus { border-color: var(--tta-black); box-shadow: var(--ring-focus); outline: none; }

/* ── Utility ── */
.empty { font: var(--type-body-s); color: var(--text-secondary); padding: 22px 14px; }
.grid-2 { display: grid; grid-template-columns: 1.3fr 1fr; gap: 24px; align-items: start; }
.msg { border-radius: var(--radius-tile); background: var(--green-050); color: var(--green-800); padding: 13px 16px; font: var(--type-body-s); }
.msg.error { background: var(--stop-050); color: var(--signal-stop); }
.eyebrow-caps { font: var(--type-micro); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-secondary); }

/* ── Login ── */
.login-wrap { min-height: 100vh; display: grid; place-items: center; background: var(--tta-black); }
.login-card { width: 380px; background: var(--tta-white); border-radius: var(--radius-card); box-shadow: var(--shadow-card); padding: 34px; display: grid; gap: 20px; }
.login-card h1 { font: var(--type-h1); letter-spacing: var(--tracking-heading); }



/* ── Checkboxes: brand green everywhere, never browser blue ─────────── */
input[type="checkbox"] { accent-color: var(--green-500); }

/* ── Dialogs — card language over a blurred scrim ────────────────────── */
/* The design asks for no modals; the product asks for a popup that blurs
   what is behind it, so these open with .showModal() and the backdrop
   carries the blur. */
dialog.modal { border: 0; padding: 0; border-radius: var(--radius-card); box-shadow: var(--shadow-raised, var(--shadow-card)); width: min(560px, calc(100vw - 48px)); max-height: calc(100vh - 80px); background: var(--surface-card, #fff); overflow: auto; }
dialog.modal::backdrop { background: rgba(16, 22, 19, .38); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
/* A dialog holds the page still behind it. */
body:has(dialog.modal[open]) { overflow: hidden; }
.modal-body { padding: 26px 28px; display: grid; gap: 18px; }
.modal-head { display: grid; gap: 4px; }
.modal-head .modal-kicker { font: var(--type-micro); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--text-secondary); }
.modal-check { display: flex; align-items: center; gap: 9px; font: var(--type-body-s); color: var(--text-primary); }
.modal-check input { width: 17px; height: 17px; }
/* Whatever grows above them, Cancel and Save stay on screen. */
.modal-actions {
  display: flex; gap: 10px; justify-content: flex-end;
  position: sticky; bottom: -26px; z-index: 1;
  margin: 0 -28px -26px; padding: 14px 28px 26px;
  background: var(--surface-card);
}

/* ── Truncated-text tooltip: instant, styled, no native title delay ─── */
.tip-wrap { position: relative; }
.tip-wrap .tip {
  display: none; position: absolute; left: 0; top: calc(100% + 6px); z-index: 40;
  max-width: 340px; width: max-content; padding: 10px 13px;
  background: var(--tta-black); color: var(--tta-white);
  font: var(--type-body-s); white-space: normal;
  border-radius: var(--radius-s); box-shadow: var(--shadow-raised);
}
.tip-wrap:hover .tip { display: block; }

:root {
  /* The disclosure chevron, from the same Lucide set as every other icon. */
  --chevron-down: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22m6%209%206%206%206-6%22/%3E%3C/svg%3E");
}

/* Disclosure.jsx on native details/summary: no marker, our own chevron, and
   a row that clears the 44px tap floor — the design's quality pass measured
   its own at 21px. */
details summary::-webkit-details-marker { display: none; }
details summary { list-style: none; }
details > summary { display: flex; align-items: center; gap: 8px; min-height: var(--tap-target-min, 44px); cursor: pointer; font: var(--type-body-s); color: var(--text-secondary); transition: var(--transition-interactive); }
details > summary:hover { color: var(--text-primary); }
details > summary::after { content: ""; width: 16px; height: 16px; flex: 0 0 auto; background: currentColor; transition: transform var(--duration-fast) var(--ease-out);
  -webkit-mask-image: var(--chevron-down); mask-image: var(--chevron-down); -webkit-mask-size: contain; mask-size: contain; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; }
details[open] > summary::after { transform: rotate(180deg); }
details > summary.quiet { min-height: 28px; }

/* NoteCard.jsx — the no-chat channel. One shared note per athlete, on the
   warm sticky-note ground the design reserves for it. */
.note-card { display: grid; gap: 14px; padding: var(--card-pad-web); background: #FDF8E7; border-radius: var(--radius-card); }
.note-card .note-head { display: flex; align-items: center; gap: 8px; font: var(--type-micro); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: #8A6A12; }
.note-card .note-head .tta-icon { color: #8A6A12; }
.note-card .note-body { font: var(--type-body); color: var(--text-primary); }
.note-card .note-meta { font: var(--type-body-s); color: var(--text-secondary); }

/* PresenceDot.jsx — who is on the app right now. Internal roles only; the
   portal never renders it for an athlete's own view. */
.presence { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.presence-dot { width: 9px; height: 9px; border-radius: 999px; flex: 0 0 auto; background: var(--grey-300); box-shadow: 0 0 0 2px var(--surface-card); }
.presence-dot.live { background: var(--tta-green); }

/* ── Task check button ─────────────────────────────────────────────── */
.task-check { width: 22px; height: 22px; border-radius: 999px; border: 1.5px solid var(--border-default); background: var(--tta-white); cursor: pointer; display: grid; place-items: center; font: var(--weight-bold) 12px/1 var(--font-body); color: transparent; transition: var(--transition-interactive); }
.task-check:hover { border-color: var(--tta-green); }
.task-check.done { background: var(--tta-green); border-color: var(--tta-green); color: var(--tta-black); }

/* task status select tints */
select.status-todo { color: var(--text-secondary); }
select.status-in_progress { color: #A96F14; }
select.status-done { color: var(--green-700); }

/* Inline form errors — said under the field, while you type, not after a
   round trip (portal/forms.js adds them). */
.field-error { display: block; margin-top: 6px; font: var(--type-body-s); color: var(--signal-stop); overflow-wrap: anywhere; }
.field input.is-invalid, .field select.is-invalid, .field textarea.is-invalid,
input.is-invalid, select.is-invalid, textarea.is-invalid { border-color: var(--signal-stop); }

/* ── Interaction states (design components/interactions.css) ──
   The tokens were already here; these are the states that were missing:
   inputs and selects on hover and focus, interactive cards and chips, and
   the press feedback on anything tappable. */
.field input:hover, .field select:hover, .field textarea:hover,
input.tta-input:hover, select.inline-select:hover { border-color: var(--grey-400); }
.field input:focus, .field select:focus, .field textarea:focus,
select.inline-select:focus { border-color: var(--tta-black); box-shadow: var(--ring-focus); outline: none; }

/* A card you can click lifts; a card you are only reading does not. */
a.card:hover, .card.clickable:hover, .card[onclick]:hover { box-shadow: var(--shadow-raised); }
a.card:active, .card.clickable:active { transform: scale(var(--press-scale-tile)); }

.pill-outline:hover { border-color: var(--tta-black); }
.seg button:hover, .tabs a:hover { background: var(--overlay-hover-light); }

.btn[disabled], .btn:disabled {
  cursor: not-allowed; transform: none; box-shadow: none;
  background: var(--grey-200); color: var(--grey-600); border-color: transparent;
}

/* Kanban columns (TasksView, OrderBoardView): one scroll wrapper, declared
   once here rather than inline on each board. */
.board-wrap { overflow-x: auto; }
.board { display: grid; grid-template-columns: repeat(3, minmax(260px, 1fr)); gap: 16px; min-width: 820px; }
.board > .col { display: grid; gap: 12px; align-content: start; }
.board .col-head { display: flex; align-items: center; gap: 8px; font: var(--type-label); color: var(--text-muted); }

/* Keyboard users get the same ring everywhere: buttons, links that act like
   buttons, rows, dialogs and the nav. (brand-states: focus is a 3px ring.) */
.row:focus-visible, dialog button:focus-visible, .nav-item:focus-visible,
.btn:focus-visible, a.card:focus-visible, summary:focus-visible,
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible {
  outline: none; box-shadow: var(--ring-focus);
}

/* Toggle.jsx — a 48×28 switch for a setting, as opposed to a checkbox for
   one of many. Pure CSS off the native checkbox, so it still posts. */
.toggle { display: flex; align-items: center; gap: 12px; cursor: pointer; min-height: var(--tap-target-min, 44px); }
.toggle input { position: absolute; opacity: 0; width: 48px; height: 28px; margin: 0; cursor: inherit; }
.toggle .track { position: relative; flex: 0 0 auto; width: 48px; height: 28px; border-radius: var(--radius-pill); background: var(--grey-300); transition: background var(--duration-fast) var(--ease-out); }
.toggle .track::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: var(--radius-pill); background: var(--tta-white); box-shadow: 0 1px 3px rgba(0,0,0,.28); transition: left var(--duration-fast) var(--ease-snap); }
.toggle input:checked + .track { background: var(--tta-green); }
.toggle input:checked + .track::after { left: 23px; }
.toggle input:focus-visible + .track { box-shadow: var(--ring-focus); }
.toggle input:disabled ~ * { opacity: .4; }
.toggle .t-text { display: grid; gap: 2px; min-width: 0; }
.toggle .t-label { font: var(--weight-bold) var(--size-body)/1.2 var(--font-body); color: var(--text-primary); }
.toggle .t-desc { font: var(--type-body-s); color: var(--text-secondary); }

/* Native checks and radios take the brand accent, like the design's range thumb. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--tta-green); width: 18px; height: 18px; cursor: pointer; }

/* Guided tour (Tour.jsx): a spotlight on the real element, one sentence, and
   the card never covering what it is pointing at. */
.tour-layer { position: fixed; inset: 0; z-index: 10000; pointer-events: none; }
.tour-mask { position: absolute; inset: 0; }
.tour-mask path { fill: rgba(12, 14, 12, .58); pointer-events: visiblePainted; }
.tour-ring { position: absolute; border-radius: 12px; box-shadow: 0 0 0 2px var(--tta-green); pointer-events: none; }
.tour-card {
  position: absolute; box-sizing: border-box; pointer-events: auto;
  background: var(--surface-card); border-radius: var(--radius-card);
  box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .5);
  padding: 16px; display: grid; gap: 12px;
}
.tour-head { display: flex; align-items: center; gap: 6px; }
.tour-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--grey-300); transition: width var(--duration-fast) var(--ease-out); }
.tour-dot.on { width: 18px; background: var(--tta-black); }
.tour-say { font: var(--type-body); text-wrap: pretty; }
.tour-actions { display: flex; gap: 8px; justify-content: flex-end; }

/* ── Upload drop zone ─────────────────────────────────────────────────── */
/* The browser's "Choose file" button is the one control we never styled.
   The native input sits hidden inside this label, so the whole box is the
   button and a dropped file is the same as a chosen one. */
.dropzone {
  display: grid; justify-items: center; gap: 8px; cursor: pointer;
  padding: 26px 18px; text-align: center;
  border: 1.5px dashed var(--grey-300);
  border-radius: var(--radius-card); background: var(--surface-sunken);
  color: var(--text-secondary); transition: var(--transition-interactive);
}
.dropzone:hover { border-color: var(--green-500); color: var(--text-primary); }
.dropzone:focus-within { outline: 2px solid var(--green-500); outline-offset: 2px; }
.dropzone.is-over { border-color: var(--green-500); background: var(--surface-accent-soft); color: var(--text-primary); }
.dropzone.has-file { border-style: solid; border-color: var(--green-500); background: var(--surface-card); }
.dropzone-say { font: var(--type-body-s); }
.dropzone-file { font: var(--weight-semibold) var(--size-body-s)/1.3 var(--font-body); color: var(--text-primary); }
.dropzone.is-missing { border-color: var(--signal-stop); }
.field-hint { display: block; margin-top: 6px; font: var(--type-body-s); color: var(--text-muted); }

/* ── Chips: pick one of a few, and un-pick it ────────────────────────── */
/* A multi-select hides both of those behind a modifier key, so a small set
   of choices is a row of chips with the native radio doing the work. */
.chip-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.chip-row .chip-label { font: var(--type-label); color: var(--text-muted); min-width: 56px; }
.chip { position: relative; display: inline-flex; cursor: pointer; }
.chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.chip span {
  display: inline-flex; align-items: center; min-height: 34px; padding: 0 14px;
  border-radius: var(--radius-pill); background: var(--surface-card);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
  font: var(--weight-medium) var(--size-body-s)/1 var(--font-body);
  color: var(--text-secondary); transition: var(--transition-interactive);
}
.chip:hover span { box-shadow: inset 0 0 0 1px var(--grey-400); color: var(--text-primary); }
.chip input:checked + span {
  background: var(--tta-green); color: var(--tta-black);
  box-shadow: none; font-weight: var(--weight-semibold);
}
.chip input:focus-visible + span { outline: 2px solid var(--green-500); outline-offset: 2px; }

/* ── Rich select: the part of a dropdown the OS used to draw ──────────── */
/* A native <select> can be styled shut but never open: the option list is an
   OS control. This is the list, in the same card language as everything
   else. The native select stays in the form and keeps working without JS. */
.rich { position: relative; }
.rich-native { position: absolute; opacity: 0; pointer-events: none; width: 100%; height: 100%; }
.rich-button {
  width: 100%; min-width: 0; display: flex; align-items: center; gap: 10px;
  height: 50px; padding: 0 15px; cursor: pointer; text-align: left;
  border: 1px solid var(--border-default); border-radius: var(--radius-input);
  background: var(--surface-card); color: var(--text-primary);
  font: var(--weight-medium) var(--size-body)/1 var(--font-body);
  transition: var(--transition-interactive);
}
.filters .rich-button, .field-s .rich-button { height: 42px; }
/* The compact one that sits in a table row. */
.rich-button.inline-select { height: 42px; font: var(--weight-medium) var(--size-body-s)/1 var(--font-body); }
.field-l .rich-button { height: 56px; }
.rich-button:hover { border-color: var(--grey-400); }
/* The select carries the invalid state; the button is what you can see. */
.rich:has(.rich-native.is-invalid) .rich-button { border-color: var(--signal-stop); }
.rich-button:focus-visible, .rich-button[aria-expanded="true"] {
  border-color: var(--tta-black); box-shadow: var(--ring-focus); outline: none;
}
.rich-button .rich-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rich-button .rich-value.is-placeholder { color: var(--text-muted); font-weight: var(--weight-regular); }
.rich-caret { flex: 0 0 auto; color: var(--text-secondary); transition: transform var(--duration-fast) var(--ease-out); }
.rich-button[aria-expanded="true"] .rich-caret { transform: rotate(180deg); }
/* Fixed, not absolute: a table card and a modal both scroll, and a list that
   clipped against their edge would be half a dropdown. JS anchors it. */
.rich-list {
  position: fixed; z-index: 60; max-height: 280px; overflow-y: auto; padding: 6px;
  background: var(--surface-card); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card); box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .45);
  display: grid; gap: 2px;
}
.rich-option {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; cursor: pointer;
  border-radius: var(--radius-tile); font: var(--type-body-s); color: var(--text-primary);
}
.rich-option:hover, .rich-option.is-active { background: var(--surface-sunken); }
.rich-option[aria-selected="true"] { font-weight: var(--weight-semibold); }
.rich-option[aria-selected="true"]::after {
  content: ""; margin-left: auto; width: 7px; height: 7px; border-radius: 999px;
  background: var(--tta-green);
}
.rich-option.is-disabled { color: var(--text-muted); cursor: default; }
.rich-group {
  padding: 8px 12px 4px; font: var(--type-label); color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .04em;
}

/* ── Phones and small tablets ─────────────────────────────────────────
   The design kit draws this portal at 1400px and has no mobile spec, so
   everything below is the same tokens re-laid out: nothing new is invented,
   the rail becomes a drawer and anything in a row becomes a column. */

.mobile-bar, .nav-scrim { display: none; }

@media (max-width: 900px) {
  /* One column, and the content starts at the top of the screen rather than
     below a full screen of navigation. */
  .shell { grid-template-columns: 1fr; }
  .grid-2, .grid-3 { grid-template-columns: 1fr; }

  .mobile-bar {
    display: flex; align-items: center; gap: 12px;
    position: sticky; top: 0; z-index: 40;
    padding: 10px 14px; background: var(--forest-900);
  }
  .mobile-logo { height: 24px; width: auto; display: block; }
  .nav-toggle {
    display: grid; place-items: center; width: 42px; height: 42px; flex: 0 0 auto;
    border: 0; border-radius: var(--radius-button); cursor: pointer;
    background: var(--overlay-hover-dark); color: var(--tta-white);
  }

  /* The rail slides over the page instead of pushing it down. */
  .sidenav {
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 60;
    width: min(290px, 84vw); height: 100dvh;
    transform: translateX(-100%);
    transition: transform var(--duration-base, .22s) var(--ease-out, ease);
    box-shadow: 0 0 60px rgba(0,0,0,.5);
  }
  .sidenav.open { transform: none; }
  .nav-scrim {
    display: block; position: fixed; inset: 0; z-index: 50;
    background: rgba(0,0,0,.5); border: 0;
  }
  .nav-scrim[hidden] { display: none; }

  /* The page title row stacks, and its buttons go full width rather than
     squeezing to nothing. */
  .toolbar {
    flex-direction: column; align-items: stretch; gap: 12px;
    padding: 16px var(--gutter-web);
  }
  .toolbar h1 { font: var(--type-display-m); letter-spacing: var(--tracking-display); }
  .toolbar .btn, .toolbar form { width: 100%; }
  .toolbar .btn { justify-content: center; }

  .page { padding: var(--gutter-web); gap: var(--stack-card, 18px); }

  /* A row of filters is a column on a phone. min-width:0 throughout: a grid
     or flex item defaults to min-width:auto, which lets a long placeholder or
     an unbreakable string widen the whole page instead of wrapping. */
  .content, .page, .toolbar, .card, .filters { min-width: 0; }
  .filters { flex-direction: column; align-items: stretch; }
  .filters .field { flex: 1 1 auto; min-width: 0; max-width: 100%; }
  .filters .field input, .filters .field select, .filters .rich, .filters .rich-button { max-width: 100%; }
  .filters > button, .filters > .btn, .filters > form > button { width: 100%; justify-content: center; }

  /* Tabs and segmented controls scroll sideways rather than wrapping into
     a ragged block or pushing the page wider than the screen. */
  .seg, .tabs {
    display: flex; width: 100%; max-width: 100%;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .seg::-webkit-scrollbar, .tabs::-webkit-scrollbar { display: none; }
  .seg a, .tabs a { flex: 0 0 auto; }

  /* The same for rows that are a table without being one. The header row
     has nothing to head once they stack, so it goes. */
  .grid-row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .grid-row-head { display: none; }

  /* A sidebar beside its content becomes the content with a list above it. */
  .split-aside, .split-main { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  /* The builder's action panel belongs under the work, not above it. */
  .split-main > :last-child { order: 2; }

  /* Kanban stays a board, one column at a time. */
  .board-wrap > .board, .board { grid-auto-flow: column; grid-auto-columns: 86vw; grid-template-columns: none; min-width: 0; }
  .board-wrap { scroll-snap-type: x mandatory; margin: 0 calc(var(--gutter-web) * -1); padding: 0 var(--gutter-web); }
  .board > .col { scroll-snap-align: start; }

  /* A dialog on a phone is a sheet: full width, off the bottom edge. */
  dialog.modal {
    width: 100%; max-width: 100%; max-height: 92dvh;
    margin: auto auto 0; border-radius: var(--radius-card) var(--radius-card) 0 0;
  }
  .modal-actions { flex-direction: column-reverse; align-items: stretch; }
  .modal-actions .btn { width: 100%; justify-content: center; }
}

/* A table does not fit a phone, and a sideways scrollbar hides half the row.
   Each row becomes a small stack instead, every value keeping the column name
   it belongs to. The labels are filled in by forms.js from the table's own
   header, so no template has to repeat them. */
@media (max-width: 760px) {
  .card:has(> .dt) { overflow-x: visible; }
  /* min-width:0 as well as width:100%: as a grid item the table would keep
     its min-content width, which is the whole point of the table it no
     longer is. */
  .card > .dt, .dt, .dt tbody, .dt tr, .dt td { display: block; width: 100%; min-width: 0; }
  .dt td > * { min-width: 0; }
  .dt thead { display: none; }
  .dt tbody tr {
    padding: 12px var(--gutter-web);
    border-bottom: 1px solid var(--border-subtle);
  }
  .dt tbody tr:last-child { border-bottom: 0; }
  .dt td {
    border: 0; padding: 5px 0;
    display: flex; gap: 12px; align-items: baseline;
  }
  /* The row's own heading, from the column this cell sits under. */
  .dt td[data-label]:not([data-label=""])::before {
    content: attr(data-label);
    flex: 0 0 38%; min-width: 0;
    font: var(--type-label); text-transform: uppercase;
    letter-spacing: var(--tracking-caps); color: var(--text-muted);
  }
  .dt td.num { text-align: left; }
  /* The action cell is the row's footer, not another labelled line. */
  .dt td:last-child { padding-top: 10px; }
  .dt td:last-child .btn { flex: 1 1 auto; justify-content: center; }
  .dt td.empty, .dt td[colspan] { display: block; text-align: center; }
  .dt td.empty::before, .dt td[colspan]::before { content: none; }
}

@media (max-width: 560px) {
  :root { --gutter-web: 16px; }
  .toolbar h1 { font: var(--type-h1); letter-spacing: var(--tracking-display); }
}
