@import url("/css/sidebar-toggle.css");

/* Cyber Academy — layout: shells, the sidebar, page header, breakpoints.
 *
 * Mobile-first: `min-width: 640px` (tablet), `832px` (the docked sidebar), `1024px` (desktop), `1440px` (wide), and a short-height class for
 * `max-height: 700px` at tablet width and above. What each shell holds is the visual contract's decision
 * (`notes/design-rulebook.md`, shells and navigation).
 *
 * SCROLL OWNERSHIP. Standalone pages use the document. Sidebar shells scroll .app__column, the viewport-height
 * content card, with the phone top bar and table headers sticky inside it. Each actual scrollport clears its
 * sticky bars on keyboard focus. The sidebar's destination list scrolls independently between its fixed header,
 * console action and account row. An open phone drawer keeps its existing behavior; only a modal locks scrolling.
 */

/* == shells == */
.app { min-height: 100vh; min-height: 100dvh; background: var(--bg); color: var(--text-1); }
.app__main { min-width: 0; padding: var(--space-6) var(--gutter) var(--space-16); }
.app__content { max-width: var(--content-max); margin-inline: auto; }
.app__content--form { max-width: var(--form-max); margin-inline: 0; }
.app--sidebar { display: block; }
@media (min-width: 832px) { .app--sidebar { display: grid; grid-template-columns: auto minmax(0, 1fr); } }
/* The page column beside the sidebar: the phone top bar, then the page. It is the content card, fixed to the viewport
 * and the one scroller of a shell with a sidebar, its scrollbar inside its own edges, so the document never scrolls.
 * From a tablet up it lies flush against the top, right and bottom edges, its left corners rounded and its shadow cast
 * onto the sidebar's chrome; the docked sidebar is then transparent, so the chrome is the shell's own background and
 * nothing covers that shadow. */
.app__column { min-width: 0; }
/* A shell with the content card never scrolls its document, so the root takes no scrollbar and no gutter: the base
 * rule that reserves one on every page (base.css) yields here, and the card's own scrollbar is the only one. */
:root:has(.app--sidebar) { scrollbar-gutter: auto; }
:root:has(.app--sidebar):not([data-scroll-lock]) { overflow-y: hidden !important; }
.app--sidebar { height: 100vh; height: 100dvh; overflow: hidden; }
.app--sidebar .app__column { height: 100vh; height: 100dvh; overflow-y: auto; overscroll-behavior: contain;
  background-color: var(--bg);
  scroll-padding-top: calc(var(--sticky-top) + var(--space-2));
  scroll-padding-bottom: calc(var(--sticky-bottom) + var(--space-2)); }
@media (min-width: 832px) {
  .app--sidebar { background: var(--chrome); }
  .app--sidebar .app__column { border-radius: var(--radius-xl) 0 0 var(--radius-xl); box-shadow: var(--elev-1); }
  /* The page title's first line (32 px) centres on the sidebar header's axis. */
  .app--sidebar .app__main { padding-top: calc(var(--header-axis) - 16px); }
}
/* A sticky table header sits under the phone's sticky top bar; from a tablet up nothing is stuck above the page and
 * the header's own default (0) holds. The one rule that offsets it. */
@media (max-width: 831px) { .app--sidebar .data-table { --sticky-offset: 56px; } }

/* Long strings never widen a page. */
.wrap-anywhere { overflow-wrap: anywhere; }

/* == layout: the product's identity in the console (client.ui.chrome/brand-lockup) == */
.brand-lockup { display: flex; align-items: center; gap: var(--space-3); flex: none; }
.brand-lockup .wordmark { display: block; height: 20px; width: auto; }
.brand-lockup .product-name { color: var(--text-2); font: var(--type-body-strong); white-space: nowrap; }

/* == layout: the sidebar (client.ui.sidebar) ==
 * One sidebar for every shell: the console (dark), a customer (branded), an account (neutral). 64 px collapsed,
 * 256 px expanded; every row 48 px inside an 8 px inset. The compact mark and `panel-left` icon
 * share the learner toggle motion: identity while collapsed, the close control while expanded. Labels stay mounted (they are the
 * accessible names) and are clipped, never reflowed, while the width animates. No stroke separates it from the page:
 * its surface against the page ground does, and the floating forms (tablet overlay, phone drawer) lift to level 3. */
/* On a phone the slot holds no width: the sidebar is a fixed drawer. On a tablet it is the 64 px rail (the expanded
 * panel overlays); on a desktop it takes the sidebar's own animated width, so expanding pushes the page. */
.sidebar-slot { position: relative; width: 0; flex: none; }
@media (min-width: 832px) { .sidebar-slot { width: auto; } }

/* A flex column exactly the viewport's height: header, the pinned console action and the footer keep their size, and
 * the destination list between them takes the rest and scrolls on its own. */
.sidebar {
  position: sticky;
  top: 0;
  z-index: var(--z-sidebar);
  display: flex;
  flex-direction: column;
  width: 64px;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  /* Clip, not a scroll container, and let the keyboard focus lift and glow of an edge-to-edge row (the console
   * action, a selected item) paint past the sidebar's own edge rather than be cut by it. Where
   * `overflow-clip-margin` is unsupported the value above stands and the glow is cut at the edge; the focus dash,
   * inside the row, is never cut. */
  overflow: clip;
  overflow-clip-margin: var(--space-4);
  background: var(--chrome);
  --surface-hover: var(--chrome-hover);
  /* THE RAIL INSET: the one horizontal inset of the header, the console action, the destinations and the account row.
   * Every row fills the width between the insets and its own padding puts its icon at 22 px (the account's avatar at
   * 16 px) from the sidebar's edge, so as the width animates every row and its fill grow and shrink with it while no
   * icon moves — the collapsed rail is simply the narrowest width, with nothing switched in or out. */
  --rail-inset: var(--space-2);
  /* ONE MOTION for everything the expand and collapse move: the width, and the tablet overlay's shadow with it. The
   * labels, brand and account name run on --dur-base and end with the width (see their delays). The toggle
   * shares the width's duration/easing through sidebar-toggle.css. */
  transition: width var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out),
              box-shadow var(--dur-slow) var(--ease-out);
}
.sidebar[data-expanded="true"] { width: 256px; }
/* From a desktop up the expanded sidebar takes 288 px (backlog item 42), so a customer's name and the product caption
 * beside its mark keep their words; the docked tablet range keeps 256 px beside its narrowest content. */
@media (min-width: 1024px) { .sidebar[data-expanded="true"] { width: 288px; } }
.sidebar__header, .sidebar__context, .sidebar__footer { flex: none; }
.sidebar__scroller { flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto; }
/* Below that height the collapsed rail's list is a scroller inside 64 px: its scrollbar is thin — a 4 px gutter,
 * reserved whether or not it is needed, holding a 4 px thumb in the same colours as every other thumb (base.css), still
 * visible at rest — and the list gives the gutter back on its right, so the square rows stay centred on the rail and on
 * the header's mark above them. In both states, so nothing about the list switches while the width animates. Firefox
 * draws its own thin scrollbar here (base.css) and ignores the gutter width. */
@media (min-width: 832px) and (max-height: 439px) {
  .sidebar__scroller { scrollbar-gutter: stable; }
  .sidebar__scroller .sidebar__nav { padding-right: calc(var(--rail-inset) - 4px); }
}
@media (min-width: 832px) and (max-height: 439px) and (not (forced-colors: active)) {
  .sidebar__scroller::-webkit-scrollbar { width: 4px; }
  .sidebar__scroller::-webkit-scrollbar-thumb { background-clip: border-box; }
}
/* Docked from 832 px (the expanded sidebar, 256 px, beside the narrowest content the console lays out, 576 px), transparent over the shell's chrome; below, the push drawer that follows, at every width. */
@media (min-width: 832px) { .sidebar { background: transparent; } }
/* Phone: the employee lesson's push drawer. The sidebar, always in the expanded layout, waits beneath on the chrome,
 * pinned to both viewport edges so it follows the dynamic viewport; the page column, the floating top bar with it, is
 * the content card that slides right to uncover it — rounding, its J1 shadow unchanged — and leaves a 64 px strip of
 * itself in view; the drawer is never wider than the docked sidebar expanded (256 px). Opening runs on slow 300 ms with the decelerate curve, closing on base 200 ms with the accelerate one;
 * an interrupted motion retraces from its current frame. The backdrop is a transparent tap target over that strip. */
@media (max-width: 831px) {
  .app--sidebar { --drawer-w: min(100vw - 64px, 256px); overflow-x: clip; background: var(--chrome); }
  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    height: auto;
    z-index: 0;
    width: var(--drawer-w);
  }
  .sidebar[data-expanded="true"], .sidebar[data-expanded="false"] { width: var(--drawer-w); }
  /* Closed, the drawer is out of the tab order and the accessibility tree, as `inert` and `aria-hidden` would put it:
   * hidden once the card has covered it, and shown the moment it starts opening. */
  .sidebar[data-open="false"] { visibility: hidden; transition: visibility 0s linear var(--dur-base); }
  .sidebar[data-open="true"] { visibility: visible; transition: visibility 0s; }
  .app--sidebar .app__column { position: relative; z-index: 1;
    transform: none; border-radius: 0; box-shadow: none;
    transition: transform var(--dur-base) var(--ease-in), border-radius var(--dur-base) var(--ease-in), box-shadow var(--dur-base) var(--ease-in); }
  .app--sidebar:has(.sidebar[data-open="true"]) .app__column { transform: translateX(var(--drawer-w)); border-radius: var(--radius-xl) 0 0 var(--radius-xl);
    box-shadow: var(--elev-1); transition-duration: var(--dur-slow); transition-timing-function: var(--ease-out); }
  .drawer-backdrop.drawer-backdrop--phone { left: var(--drawer-w); background: transparent; }

  /* One toggle: the floating menu button riding on the strip opens and closes the drawer, as in the lesson. */
  .sidebar .sidebar__toggle { display: none; }
}

/* One header for both states — 64 px (56 in a short window) with 8 px above its content — so opening or closing the
 * sidebar moves nothing up or down. Collapsed, the rail is one uniform stack: the logo tile is exactly a rail button
 * (48 px, 40 px in a short window), with its radius and its centring, and stands 12 px below the top — the same 12 px
 * that parts it from the first item (the header's 4 px below it and the nav's 8 px). */
/* The toggle stays at the right inset in both states: in the collapsed rail that is where centring put it, and it rides
 * the right edge through the transition rather than snapping to the centre when the collapse begins. */
.sidebar__header { position: relative; display: flex; align-items: center; justify-content: flex-end; height: 64px; padding: var(--space-2) var(--rail-inset) 0; }
/* The rail logo keeps one size: it is only ever seen in the collapsed rail, and a size tied to the state would snap
 * while it fades. */
.sidebar__toggle-logo .logo-tile { --logo-size: 48px; }
.sidebar__toggle {
  position: relative;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard);
}
/* Hover and focus identify the control without replacing the collapsed customer mark. */
@media (hover: hover) { .sidebar__toggle:hover { background: var(--surface-hover); } }
/* The expanded header's identity, standing where the collapsed toggle's mark stood: centred on the header's height,
 * so a one-line lockup and a two-line one (a customer's wide logo or name over the product caption) sit alike. */
.sidebar__brand {
  position: absolute;
  left: 16px;
  top: var(--space-2);
  bottom: 0;
  right: 64px;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out);
}
.sidebar[data-expanded="true"] .sidebar__brand { opacity: 1; transition-delay: var(--delay-label-in); }
.sidebar[data-expanded="false"] .sidebar__brand { opacity: 0; transition-delay: 0ms; }
/* The identity is the link home (operator 2026-10-18): its own box, so its focus dash sits under it, and the
 * colour-only hover of a text control on its words; unreachable while the collapsed rail hides it. */
.sidebar__home { display: flex; align-items: center; gap: var(--space-3); min-width: 0; color: inherit; text-decoration: none; pointer-events: auto; }
.sidebar__home :is(.sidebar__caption, .sidebar__customer-name, .product-name, .t-name) { transition: color var(--dur-fast) var(--ease-standard); }
@media (hover: hover) {
  .sidebar__home:hover :is(.sidebar__caption, .sidebar__customer-name, .product-name, .t-name) { color: var(--text-hover); }
}
@media (min-width: 832px) { .sidebar[data-expanded="false"] .sidebar__home { pointer-events: none; } }
.sidebar__lockup { display: flex; flex-direction: column; justify-content: center; min-width: 0; }
/* The wide logo placement: at most 28 px tall and 144 px wide, never cropped. */
.sidebar__wide-logo { display: block; max-width: 144px; max-height: 28px; width: auto; height: auto; object-fit: contain; object-position: left center; }
/* A wide logo and the product caption share one line, centred on the header: the caption keeps its width and the logo
 * gives way — at most 24 px tall, shrinking to the room left, contained and never cropped. */
.sidebar__lockup--inline { flex-direction: row; align-items: center; gap: var(--space-2); }
.sidebar__lockup--inline .sidebar__wide-logo { flex: 0 1 auto; min-width: 0; height: 24px; max-height: 24px; }
.sidebar__lockup--inline .sidebar__caption { flex: none; }
.sidebar__customer-name { overflow: hidden; text-overflow: ellipsis; color: var(--text-1); font: var(--type-name); }
.sidebar__caption { color: var(--text-3); font: var(--type-caption); letter-spacing: var(--track-caption); }
/* The drawer is always drawn expanded, whatever the rail was left at; these outrank the collapsed rules. */
@media (max-width: 831px) {
  .sidebar[data-expanded] .sidebar__brand { opacity: 1; }
  .sidebar[data-expanded] .sidebar__toggle-logo { opacity: 0; }
  .sidebar[data-expanded] .sidebar__toggle-icon { opacity: 1; transform: scale(1); }
}
/* A customer's mark: its logo on white, or its monogram on the brand secondary. Organisations are rounded squares. */
.logo-tile {
  display: grid;
  place-items: center;
  flex: none;
  width: var(--logo-size, 32px);
  height: var(--logo-size, 32px);
  border-radius: var(--radius-md);
  background: var(--logo-ground);
  overflow: hidden;
}
.logo-tile > img { width: 100%; height: 100%; padding: 3px; object-fit: contain; }
/* The square icon is made for the tile: it fills it edge to edge and the radius clips its corners. A full logo standing
 * in for a missing icon keeps its inset and is contained, since cropping would cut the wordmark. */
.logo-tile--icon > img { padding: 0; object-fit: cover; }
.logo-tile--monogram { background: var(--brand-secondary, var(--accent)); color: var(--monogram-ink, var(--accent-ink)); font: var(--weight-medium) var(--text-14) / 1 var(--font-sans); }
.logo-tile--placeholder { background: var(--surface-2); }
.logo-tile--24 { --logo-size: 24px; }
.logo-tile--28 { --logo-size: 28px; }
.logo-tile--32 { --logo-size: 32px; }
/* The product's own mark in the console and an account shell: the academy glyph on the mode's accent tile. */
.product-glyph { display: grid; place-items: center; flex: none; border-radius: var(--radius-md); background: var(--accent); color: var(--accent-ink); }
.product-glyph--28 { width: 28px; height: 28px; }
.product-glyph--32 { width: 32px; height: 32px; }

/* The destinations. The list's own inset keeps a row's hover and selected fill clear of the scroller's edges. */
.sidebar__nav { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-2) var(--rail-inset); margin: 0; list-style: none; }
/* Each row fills the rail: the item (and its selected fill) is as wide as the row, whatever its label. */
.sidebar__nav > li { display: flex; }
.sidebar__nav > li .sidebar__item { flex: 1; min-width: 0; width: 100%; }
.sidebar__item {
  position: relative;
  display: flex;
  align-items: center;
  height: 48px;
  padding-left: calc(22px - var(--rail-inset));
  border-radius: var(--radius-md);
  color: var(--text-2);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  transition: background-color var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
@media (hover: hover) { .sidebar__item:hover { background-color: var(--surface-hover); color: var(--text-1); } }
.sidebar__item:active { background-color: var(--surface-pressed); transition-duration: var(--dur-instant); }
.sidebar__item > svg { flex: none; }
.sidebar__label {
  margin-left: var(--space-3);
  font: var(--type-body-strong);
  white-space: nowrap;
  overflow: hidden;
  transition: opacity var(--dur-base) var(--ease-out);
}
/* Labels fade in once the width has made room, as the brand does, and fade out at once as the rail closes. */
.sidebar[data-expanded="true"] .sidebar__label { transition-delay: var(--delay-label-in); }
.sidebar[data-expanded="false"] .sidebar__label { opacity: 0; }
@media (max-width: 831px) { .sidebar[data-expanded] .sidebar__label { opacity: 1; } }
/* Selected: a filled pill in the accent tint, the 600 label and the icon in the accent — never a bar, never the tint
 * alone. The selected fill outranks hover and keyboard focus. Focused, the pill also lifts a step (level 1) besides
 * its dash, so focus on the selected item is a change of more than one mark. The dash, in the focus colour on the
 * tint, measures 11.94:1 (lime on the dark tint), 7.67:1 (default purple on the light tint) and 16.02:1 (neutral ink);
 * a brand primary at the 4.5:1 floor keeps about 4.0:1 on its own 10 % tint, above the 3:1 a focus cue needs. */
.sidebar__item[aria-current="page"],
.sidebar__item[aria-current="page"]:hover,
.sidebar__item[aria-current="page"]:focus-visible { background-color: var(--accent-tint); color: var(--text-1); }
.sidebar__item[aria-current="page"]:focus-visible { box-shadow: var(--elev-1); }
.sidebar__item[aria-current="page"] > svg { color: var(--accent); }
.sidebar__item[aria-current="page"] .sidebar__label { font-weight: var(--weight-semibold); }

/* The superadmin's pinned way back to the console, inside a customer: the console's own dark surface and lime icon on
 * the customer's light sidebar, so it reads as the operator's action (`notes/design-rulebook.md` §4). Its colours are
 * the console's named primitives (tokens.css, `--console-*`), read directly because this row lives inside the
 * customer mode and a nested `data-mode` would repaint the whole document's ground. It lifts on the ladder and takes
 * the filled control's keyboard focus (fill step, lift, glow, a dash in its own ink). The space under it keeps the
 * dark square apart from the selected item below, so it never reads as the current one. */
.sidebar__context { display: flex; padding: var(--space-2) var(--rail-inset); }
.sidebar__console-link {
  --fill-hover: var(--console-surface-hover);
  --fill-shadow-2: var(--elev-2);
  position: relative;
  display: flex;
  flex: 1;
  align-items: center;
  min-width: 0;
  height: 48px;
  padding-left: calc(22px - var(--rail-inset));
  border-radius: var(--radius-md);
  background-color: var(--console-surface);
  color: var(--console-ink);
  box-shadow: var(--elev-1);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  transition: background-color var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard);
}
.sidebar__console-link > svg { flex: none; color: var(--console-accent); }
@media (hover: hover) { .sidebar__console-link:hover { background-color: var(--console-surface-hover); box-shadow: var(--elev-2); } }
.sidebar__console-link:active { background-color: var(--console-surface); box-shadow: var(--elev-1); transition-duration: var(--dur-instant); }

.sidebar__footer { padding: var(--space-2) var(--rail-inset); }
/* The account row stays within the rail; its menu renders in the shell overlay root. */
.sidebar__account {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  height: 48px;
  padding: 0 calc(16px - var(--rail-inset));
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-1);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  transition: background-color var(--dur-fast) var(--ease-standard);
}
@media (hover: hover) { .sidebar__account:hover { background-color: var(--surface-hover); } }
/* On the profile the row opens, the row is the current page: the selected pill of a destination, lifting on focus. */
.sidebar__account[aria-current="page"],
.sidebar__account[aria-current="page"]:hover,
.sidebar__account[aria-current="page"]:focus-visible { background-color: var(--accent-tint); }
.sidebar__account[aria-current="page"] .sidebar__account-name { font-weight: var(--weight-semibold); }
.sidebar__account[aria-current="page"]:focus-visible { box-shadow: var(--elev-1); }
.sidebar__account-name { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font: var(--type-body-strong); transition: opacity var(--dur-base) var(--ease-out); }
.sidebar[data-expanded="true"] .sidebar__account-name { transition-delay: var(--delay-label-in); }
.sidebar[data-expanded="false"] .sidebar__account-name { opacity: 0; }
@media (max-width: 831px) { .sidebar[data-expanded] .sidebar__account-name { opacity: 1; } }

.drawer-backdrop { position: fixed; inset: 0; z-index: var(--z-backdrop); border: 0; padding: 0; background: var(--backdrop); cursor: default; }
@media (min-width: 832px) { .drawer-backdrop--phone { display: none; } }
/* Behind the expanded panel only where it overlays the page: a tablet. The sidebar sits above it. */

/* The phone's top bar, for every shell with a sidebar, as the employee lesson composes it: no bar of its own, but a
 * round floating menu button and, 8 px beside it, the identity as a floating pill of the same height, both on the
 * surface at level 2, 12 px from the edges. The row keeps the 56 px the sticky table headers are offset by. */
.mobile-topbar {
  --float-size: 40px;
  position: sticky;
  top: 0;
  z-index: var(--z-topbar);
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  height: 56px;
  padding: calc(var(--header-axis) - var(--float-size) / 2) var(--space-3) 0;
}
@media (pointer: coarse) { .mobile-topbar { --float-size: 44px; } }
.mobile-topbar > .icon-btn { flex: none; width: var(--float-size); height: var(--float-size); border-radius: var(--radius-full);
  background: var(--surface); box-shadow: var(--elev-2); }
.mobile-topbar__identity { display: flex; align-items: center; gap: var(--space-3); min-width: 0; height: var(--float-size);
  padding: 0 var(--space-4); border-radius: var(--radius-full); background: var(--surface); box-shadow: var(--elev-2); }
/* The pill fades out as the drawer opens (the drawer's own header names the shell then) and back as it closes, on
 * the card's own timing; the menu button stays. */
.mobile-topbar__identity { transition: opacity var(--dur-base) var(--ease-in); }
.app--sidebar:has(.sidebar[data-open="true"]) .mobile-topbar__identity { opacity: 0; transition-duration: var(--dur-slow); transition-timing-function: var(--ease-out); }
.mobile-topbar .wordmark { display: block; height: 18px; width: auto; }
/* A logo alone: inline padding equal to the space above and below the mark, so it sits centred in a compact pill. */
.mobile-topbar__identity--logo { padding: 0 var(--space-3); }
.mobile-topbar__logo { display: block; height: 24px; max-width: 160px; width: auto; object-fit: contain; }
.mobile-topbar__title { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
@media (min-width: 832px) { .mobile-topbar { display: none; } }

/* == layout: page header (client.ui.page/page-header) == */
.page-header { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-4); align-items: start; margin-bottom: var(--card-gap); }
.page-header__main { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.page-header__title { color: var(--text-1); overflow-wrap: anywhere; }
.page-header__title:focus { outline: none; }
.page-header__count { color: var(--text-3); font-weight: var(--weight-regular); margin-left: var(--space-2); font-variant-numeric: tabular-nums; }
.page-header__meta { color: var(--text-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.page-header__actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; justify-content: flex-end; min-height: var(--lh-24); }
@media (max-width: 639px) {
  .page-header { grid-template-columns: minmax(0, 1fr); }
  .page-header__actions { justify-content: flex-start; }
  .page-header__actions > .btn:only-child { width: 100%; }
}
.section-header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-3); }
.section-header__title { display: flex; align-items: center; min-width: 0; color: var(--text-1); }
/* The count badge stays on its title's line; the header's acts wrap below on a narrow screen instead. */
.section-header { flex-wrap: wrap; }
.section-header__mark { display: inline-flex; margin-left: auto; }
.section-header__count { color: var(--text-3); font-weight: var(--weight-regular); margin-left: var(--space-2); }
.section + .section { margin-top: var(--space-10); }
/* A notice directly under the page header or a section heading keeps the rhythm of what it follows: the page gap
 * below a page notice, the heading's gap below a section's. */
.page-header ~ :is(.notice, .refresh-failure) { margin-bottom: var(--card-gap); }
.section-header + .notice { margin-bottom: var(--space-3); }
/* A page stack: a page's blocks one under the other, one gap apart. A block keeps no flow margin of its own inside
 * it — the rule that clears them closes this file, so it follows every block's own. */
.page-stack { display: flex; flex-direction: column; gap: var(--card-gap); min-width: 0; }
/* A section's pager: its two acts at the end edge, under what they page. */
.section-pager { display: flex; justify-content: flex-end; gap: var(--space-2); }
.toolbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-3); }
/* A segmented switch too wide for a phone (Administration's four groups): the segmented control from 640 px, the
 * shared select below it, full width — the one shown, the other not rendered to anyone. */
.segment-switch__narrow { display: none; width: 100%; }
@media (max-width: 639px) {
  .segment-switch__wide { display: none; }
  .segment-switch__narrow { display: block; }
}
.toolbar__end { margin-left: auto; display: flex; gap: var(--space-2); flex-wrap: wrap; }
.charts-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--card-gap); }
@media (min-width: 1200px) { .charts-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* == layout: neutral shell (pre-authentication, unassigned-administrator landing) == */
.preauth { min-height: 100vh; min-height: 100dvh; padding: 12vh var(--space-4) var(--space-8); background: var(--bg); }
.preauth__card { --holder: var(--surface); --holder-below: var(--bg); width: min(400px, 100%); margin: 0 auto; padding: var(--space-8); background-color: var(--surface); border-radius: var(--radius-lg); box-shadow: var(--elev-1); }
.product-mark { display: flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-6); color: var(--text-1); font: var(--type-name); }
.product-mark__glyph { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; flex: none; clip-path: polygon(4px 0, calc(100% - 4px) 0, 100% 4px, 100% calc(100% - 4px), calc(100% - 4px) 100%, 4px 100%, 0 calc(100% - 4px), 0 4px); background: var(--console-accent); color: var(--console-surface); }
.preauth__outcome { display: flex; flex-direction: column; gap: var(--space-6); }
.preauth__card > .preauth__outcome > p { margin: 0; color: var(--text-1); }
.preauth__card > .preauth__outcome > .btn { margin-top: 0; }
.preauth__card > .btn--ghost { margin: 0 0 var(--space-2) -10px; }
.preauth__title { margin: 0 0 var(--space-2); color: var(--text-1); font: var(--type-title-1); }
.preauth__title:focus { outline: none; }
.product-mark:focus { outline: none; }
.preauth__subtitle { margin: 0 0 var(--space-6); color: var(--text-2); font: var(--type-small); overflow-wrap: anywhere; }
.preauth__error { margin-bottom: var(--space-4); }
.preauth__card form { display: flex; flex-direction: column; }
.preauth__card form > .notice { margin-bottom: var(--space-4); }
.preauth__card .input { height: var(--control-h-lg); }
.preauth__card form > .btn, .preauth__card > div > .btn, .preauth__card > .btn { width: 100%; height: var(--control-h-lg); margin-top: var(--space-2); }
.preauth__card form > .btn--ghost { width: auto; align-self: flex-start; }
.preauth__actions { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: var(--space-2); margin-top: var(--space-2); }
.preauth__actions > .btn { width: 100%; height: var(--control-h-lg); }
/* The line under the mark sits midway between the mark and what follows: 16 px above and below it. */
.preauth__card > .product-mark:has(+ .preauth__subtitle) { margin-bottom: var(--space-4); }
.preauth__card > .product-mark + .preauth__subtitle { margin-bottom: var(--space-4); }
.preauth__card > .product-mark + .preauth__subtitle + .btn { margin-top: 0; }
.preauth__card > div > p { color: var(--text-2); }
.preauth__aside { margin: var(--space-4) 0 0; text-align: right; font: var(--type-small); }
.identity-qr svg { display: block; width: min(100%, 192px); height: auto; margin: var(--space-4) auto; background: var(--logo-ground); }
/* The authenticator step: the instruction, the QR, the manual-key fallback and the code, evenly spaced. The key is two
 * lines of four groups (`client.ui.qr/grouped-key`), centred, with its copy button centred under it. */
.identity-provisioning { display: flex; flex-direction: column; gap: var(--space-3); }
.identity-provisioning > p { margin: 0; }
.identity-provisioning .identity-qr svg { margin: 0 auto; }
/* "nebo" between the QR code and the key: centred, muted, and held equally far from both by the column's gap. */
.identity-provisioning > .identity-or { text-align: center; color: var(--text-2); }
.identity-key-row { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); }
.identity-key-row > [role="group"] > .identity-key { margin: 0; }
.identity-key-row > [role="group"] { display: flex; flex-direction: column; gap: 6px; align-self: stretch; }
.identity-key { display: block; text-align: center; white-space: pre-line; font-family: var(--font-mono); letter-spacing: 0.08em; line-height: var(--lh-16); }
@media (max-width: 639px) {
  .preauth { padding: 0; background: var(--surface); }
  .preauth__card { border-radius: 0; box-shadow: none; padding: 48px 16px; }
}

/* == short height (desktop width) == */
@media (max-height: 700px) and (min-width: 832px) {
  .sidebar__header { height: 56px; }
  /* The rows are 40 px tall, and a 12 px rail inset makes them 40 px wide in the 64 px collapsed rail — square, as the
   * logo tile is — while their padding still puts every icon where the 48 px rows do. Nothing switches with the state,
   * so the fills shrink and grow with the width. */
  .sidebar { --rail-inset: 12px; }
  .sidebar__toggle { width: 40px; height: 40px; }
  .sidebar__toggle-logo .logo-tile { --logo-size: 40px; }
  .sidebar__item, .sidebar__account, .sidebar__console-link { height: 40px; }
  .app__main { padding-top: var(--space-4); }
}

/* == layout: the customer frame and its destinations == */
.customer-page > .refresh-failure { margin-bottom: var(--card-gap); }
.employees-switch, .report-sections { margin-bottom: var(--card-gap); }
/* A tile grid (client.ui.tile's, in components.css) in the flow of a page stands one page gap above what follows. */
.stat-grid { margin-bottom: var(--card-gap); }
.report-filters__period { display: flex; flex-direction: column; gap: var(--space-2); }
.report-filters__label { color: var(--text-1); font: var(--type-label); }

/* == layout: the Reports page's control card (client.views.customer.reports/controls-card) ==
 * One raised card above the panel it governs, with the table card's surface, level and radius — the filter card of
 * the Employees and Runs lists in all but name: the sections stand above it as the Employees view switch does, and
 * the export is the page header's act. Inside, the filters, each group a grid of equal columns so its fields align in
 * rows whatever their number, the rows 12 px apart as the filter card's; and the footer, the trend window at its start
 * and "Vymazat filtry" at its end. The layout follows the card's own width, never the viewport's: a narrow card puts
 * two fields to a row, as the filter card does on a phone, and gives the trend window its full row. The partner's aggregate report draws the
 * same card without sections or exports. Its padding, inner gap and the gap below it are the filter card's, so the
 * three list pages open alike (Employees, Runs, Reports). */
.report-controls { --holder: var(--surface); --holder-below: var(--bg); container: report-controls / inline-size; display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--card-gap); padding: var(--space-3) var(--space-4) var(--space-4); background-color: var(--surface); border-radius: var(--radius-lg); box-shadow: var(--elev-1); min-width: 0; }
.report-controls__filters { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.report-controls__group { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); align-items: end; gap: var(--space-3) var(--space-4); min-width: 0; }
.report-controls__group > .form-field { max-width: none; min-width: 0; margin: 0; }
.report-controls__group .segmented { display: flex; width: 100%; }
.report-controls__group .segmented__item { flex: 1; justify-content: center; }
.report-controls__footer { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-4); }
.report-controls__exports { display: flex; align-items: center; gap: var(--space-1); }
@container report-controls (max-width: 519px) {
  .report-controls__group { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  /* A group of one field (the partner's aggregate card) keeps the narrow card's whole width. */
  .report-controls__group > :only-child { grid-column: 1 / -1; }
  .report-controls__footer > .report-filters__period { flex: 1 1 100%; }
  .report-controls__footer .segmented { display: flex; width: 100%; }
  .report-controls__footer .segmented__item { flex: 1; justify-content: center; }
}
@media (max-width: 639px) { .report-controls { padding: var(--space-3); } }
/* A section's as-of line with its help beside it: the line in `text-2`, the help's icon button on its baseline. */
.report-meta { display: flex; align-items: center; gap: var(--space-1); margin: 0 0 var(--space-3); color: var(--text-2); font: var(--type-small); }
.report-activity { --holder: var(--surface); --holder-below: var(--bg); display: flex; flex-direction: column; gap: var(--space-3); padding: var(--card-pad); background-color: var(--surface); border-radius: var(--radius-lg); box-shadow: var(--elev-1); min-width: 0; }
/* The card's own gap stands in for its heading's, so the heading sits as close to what follows as in any card. */
.report-activity > .section-header { margin-bottom: 0; }
.report-activity .data-table th { position: static; }
.report-activity .data-table tbody tr:last-child th, .chart-card__table .data-table tbody tr:last-child th { border-bottom: 0; }
.report-activity .data-table th[scope="row"], .chart-card__table .data-table th[scope="row"] { height: var(--row-h); color: var(--text-1); font: var(--type-body); letter-spacing: 0; white-space: normal; overflow-wrap: anywhere; }

/* == layout: customer settings (client.views.customer.settings) ==
 * One surface holds the three configuration phases; management sits apart at its foot. */
.settings { container: settings / inline-size; display: flex; flex-direction: column; gap: var(--card-gap); }
.settings-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-8) var(--space-10); align-items: start; }
/* Three cards (operator 2026-10-18): the launch checklist, Identita — the names on the left, the logos beside them,
 * the colours with their live preview across below — and Vzdělávání a hlášení incidentů on its own. */
@container settings (min-width: 900px) {
  .settings-form { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .settings-section--identity { grid-column: 1; }
  .settings-section--logos { grid-column: 2; grid-row: 1; }
  .settings-section--colours { grid-column: 1 / -1; }
}
.settings-section--identity .form-stack, .settings-section--identity { display: flex; flex-direction: column; gap: var(--space-4); }
.settings-readonly { margin: 0; color: var(--text-1); }
/* Responsive rule (operator 2026-10-18): the page has ONE layout breakpoint, the identity/logos split at 900 px of the
 * settings column; everything inside a card reflows by that card's own width (`card` container), never by the
 * viewport or by a wider ancestor, so a card in a half column lays out as narrow as it is. */
.settings-section { min-width: 0; }
.settings-section, .settings-card { container: card / inline-size; }
.settings-section--identity .form-field { max-width: var(--form-max); }
/* Settings is one page stack of cards (`.page-stack`); the last row keeps the same gap between its two. */
/* No card in a stack carries a margin of its own: the stack's one gap is the whole rhythm. */
.page-stack > *, .settings > *, .settings-final-row > * { margin-block: 0; }
/* A section in a page stack takes the stack's one gap, never a margin of its own above it (page rhythm). */
.page-stack > .section + .section, .page-stack > * + .section { margin-top: 0; }
.page-stack > .readiness { margin-block: 0; }
/* Spuštění služby: the state at the top, its act anchored bottom-right. */
.launch-card { display: flex; flex-direction: column; }
.launch-card .readiness-launched { flex: 1; flex-direction: column; align-items: stretch; justify-content: space-between; gap: var(--space-4); }
.launch-card .readiness-launched > .btn { align-self: flex-end; }
/* The last row: Spuštění služby left, Správa right, half the width each; stacked when narrow. */
.settings-final-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr)); gap: var(--card-gap); align-items: stretch; }
.settings-final-row:empty { display: none; }
.settings-lifecycle { display: flex; flex-direction: column; gap: var(--space-3); }
.logo-assets { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
@container card (min-width: 440px) { .logo-assets { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.logo-asset { display: flex; flex-direction: column; min-width: 0; }
.logo-asset .import-drop { --holder: var(--surface); --holder-below: var(--bg); height: 160px; flex-direction: column; justify-content: center; text-align: center; padding: var(--space-4); }
.logo-asset .import-drop__icon, .logo-asset__image { display: grid; place-items: center; height: 64px; width: 100%; min-width: 0; }
.logo-asset--icon .logo-asset__image { width: 64px; }
.logo-asset__image img { display: block; max-width: 100%; max-height: 64px; object-fit: contain; }
.logo-asset .import-drop__text { align-items: center; }
.logo-asset__footer { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); min-height: var(--lh-12); margin-top: var(--space-2); }
/* Vzdělávání a hlášení incidentů (operator 2026-10-18): the language beside the reporting channel and its contact
 * where the card is wide, stacked where it is narrow; the channel's save state directly under its field. */
/* Content-driven, no breakpoint (operator 2026-10-18): the language, the reporting channel and its contact stand on
 * one line while it holds them, each at a field's width, and wrap one by one as it narrows — the same rule inside the
 * launch checklist's third step, whose narrow column stacks them. */
.learning-settings { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-5) var(--space-8); }
.learning-settings > .learning-settings__locale { flex: none; }
.learning-settings > .learning-settings__reporting { flex: 1 1 18rem; min-width: 0; }
.learning-settings__reporting { flex-direction: row; flex-wrap: wrap; align-items: flex-start; gap: var(--space-4) var(--space-5); }
.learning-settings__reporting > * { flex: 1 1 14rem; min-width: 0; max-width: var(--field-max); }
/* A field a choice reveals opens to its height rather than appearing at it. */
.field-reveal { display: grid; animation: field-reveal var(--dur-slow) var(--ease-out); }
.field-reveal > * { min-height: 0; overflow: clip; overflow-clip-margin: var(--space-1); }
@keyframes field-reveal { from { grid-template-rows: 0fr; opacity: 0; } to { grid-template-rows: 1fr; opacity: 1; } }
.readiness-row__control { margin-top: var(--space-2); }
.settings-colour-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); align-items: start; }
@container card (min-width: 760px) { .settings-colour-layout { grid-template-columns: minmax(320px, 360px) minmax(0, 1fr); } }
.settings-colour-controls { min-width: 0; }
.colour-roles { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
.colour-role { min-width: 0; }
/* The form's actions are set apart by 24 px of space, not a rule. */
.form-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-6); }
.save-confirmation { margin: 0 0 var(--space-4); color: var(--status-on-track-fg); }
/* Správa: one grid for both rows, the headings taking the spare width and the actions sharing a right edge; the rows
 * stack when the card itself is narrow. */
.lifecycle__rows { display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; column-gap: var(--space-8); row-gap: var(--space-3); }
.lifecycle__state, .lifecycle__row { display: contents; }
.lifecycle__title { margin: 0; }
.lifecycle__rows .btn { justify-self: end; }
@container card (max-width: 419px) {
  .lifecycle__rows { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-2); }
  .lifecycle__rows .btn { justify-self: start; margin-bottom: var(--space-4); }
}
/* The one operator mark of a section only an operator sees: the shield beside its heading. */
.operator-heading { display: inline-flex; align-items: center; gap: var(--space-2); }
.operator-heading__mark { display: inline-flex; padding: 2px; color: var(--text-3); }
/* The live preview: the real components under the brand being chosen, in a recess of the page's own ground — sunk into
 * the panel by the well's inset shadow, never lifted by a drop shadow (decided by the operator 2026-09-28). Its sidebar
 * panels are the white surface the real sidebar is, so the brand is previewed on the surfaces it will sit on. */
.brand-preview { --holder: var(--bg); display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-5); border-radius: var(--radius-lg); background: var(--bg); box-shadow: var(--inset-rest); color: var(--text-1); }
.brand-preview__caption { margin: 0; color: var(--text-3); font: var(--type-caption); letter-spacing: var(--track-caption); }
.brand-preview__panels { display: flex; gap: var(--space-3); }
.brand-preview__rail { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-1); border-radius: var(--radius-md); background: var(--surface); }
.brand-preview__rail-item { justify-content: center; width: 40px; height: 40px; padding: 0; }
.brand-preview__sidebar { display: flex; flex: 1; flex-direction: column; gap: var(--space-1); min-width: 0; padding: var(--space-2); border-radius: var(--radius-md); background: var(--surface); }
.brand-preview__brand { display: flex; align-items: center; gap: var(--space-2); min-width: 0; height: 32px; }
.brand-preview__wide { display: block; max-width: 176px; max-height: 32px; object-fit: contain; object-position: left center; }
.brand-preview__name { overflow: hidden; font: var(--type-name); white-space: nowrap; text-overflow: ellipsis; }
.brand-preview__product { margin-bottom: var(--space-1); color: var(--text-2); font: var(--type-small); }
.brand-preview__item { height: 40px; }
.brand-preview__buttons { display: flex; gap: var(--space-2); }
.brand-preview__buttons .btn { height: var(--control-h-sm); padding: 0 var(--space-2); font-size: var(--text-13); }
.brand-preview__button { display: inline-flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); }
.brand-preview__hover { background-color: var(--accent-hover); box-shadow: var(--elev-2-fill); }
.brand-preview__pressed { background-color: var(--accent-pressed); box-shadow: var(--elev-1-fill); }
.brand-preview__note { color: var(--text-3); font: var(--type-small); }
.brand-preview__text { margin: 0; }
.brand-preview__link { color: var(--link); text-decoration: underline; text-underline-offset: 2px; }
.brand-preview__marks { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.brand-preview__check { display: inline-flex; align-items: center; gap: var(--space-2); }
.brand-preview__checked { display: inline-grid; place-items: center; width: 16px; height: 16px; border-radius: var(--radius-xs); background-color: var(--accent); color: var(--accent-ink); }
.brand-preview__stepper { margin: 0; }
.brand-preview__print { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); border-radius: var(--radius-md); background: var(--logo-ground); box-shadow: var(--elev-1); }
.brand-preview__print-logo { max-width: 220px; max-height: 48px; object-fit: contain; }
.brand-preview__print-icon { width: 48px; height: 48px; object-fit: contain; }
.brand-preview__print-title { color: var(--text-1); font: var(--type-name); }
.brand-preview__monogram { display: flex; align-items: center; gap: var(--space-2); }
.brand-preview [data-brand-role] { transition: opacity var(--dur-fast) var(--ease-standard); }
.brand-preview[data-role="primary"] [data-brand-role="secondary"],
.brand-preview[data-role="secondary"] [data-brand-role="primary"] { opacity: 0.28; }
/* An operator-only control: the shield before its label (design synthesis §6.2). */
.operator-only { display: inline-flex; align-items: center; gap: 6px; }
.operator-only__mark { display: inline-flex; color: var(--text-3); }

/* == layout: people lists (Administration, a customer's administrators) == */
.status-slot:empty { display: none; }
.status-slot { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-4); }
.status-slot > .status-line:focus { outline: none; }
.person { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; flex-wrap: wrap; }
.person__name { color: var(--text-1); font-weight: var(--weight-medium); overflow-wrap: anywhere; }
.person__tags { display: inline-flex; gap: var(--space-1); flex-wrap: wrap; }
.person__tags:empty { display: none; }
.person-line { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); min-width: 0; }
.page-notices { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-6); }
.page-notices:empty { display: none; }
.row-actions { display: flex; justify-content: flex-end; }
/* A list whose rows open an actions menu lets the menu out of its card rather than clipping it; the card's rounded
 * corners are then drawn by the first and last things inside it instead of by the clip. */
.table-card:has(.row-actions) { overflow: visible; }
.table-card:has(.row-actions) .inline-create__trigger,
.table-card:has(.row-actions) .inline-create__form { border-radius: calc(var(--radius-lg) - 1px) calc(var(--radius-lg) - 1px) 0 0; }
.table-card:has(.row-actions) .data-table tbody tr:last-child td:first-child { border-bottom-left-radius: calc(var(--radius-lg) - 1px); }
.table-card:has(.row-actions) .data-table tbody tr:last-child td:last-child { border-bottom-right-radius: calc(var(--radius-lg) - 1px); }
.table-card:has(.row-actions) .list-item:last-child { border-radius: 0 0 calc(var(--radius-lg) - 1px) calc(var(--radius-lg) - 1px); }
/* The row trigger sits at the right edge: its tooltip opens leftwards so it never widens the page, and a long
 * unbroken address in its name (people who share a name are told apart by it) wraps rather than overflowing. */

.tag-row { display: flex; flex-wrap: wrap; gap: var(--space-1); align-items: center; }
.tag-help > [tabindex] { display: inline-flex; border-radius: var(--radius-xs); }
.toolbar .search-field { width: 320px; max-width: 100%; }
@media (max-width: 639px) {
  .toolbar .search-field { width: 100%; }
  .toolbar__end { margin-left: 0; width: 100%; }
  .toolbar__end > .search-field-group { width: 100%; }
}

/* == layout: Administration's audit export (client.views.administration/audit-export-panel) ==
 * One panel under the list: its lead and scope at reading width, the period and the filters in one wrapping row,
 * the two downloads at the end edge. */
.audit-export { display: flex; flex-direction: column; gap: var(--space-4); margin-top: var(--card-gap); }
.audit-export .section-header, .audit-export .status-slot { margin: 0; }
.audit-export__lead, .audit-export__scope { max-width: 680px; margin: 0; color: var(--text-2); }
.audit-export__fields { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.audit-export__fields > .form-field { flex: 1 1 200px; min-width: 0; max-width: 320px; }
.audit-export__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); }
@media (max-width: 639px) {
  .audit-export { padding: var(--space-4); }
  .audit-export__fields > .form-field { flex-basis: 100%; max-width: none; }
  .audit-export__actions > .btn { flex: 1 1 auto; }
}

/* == layout: the profile page ==
 * Cards on the elevation system (operator 2026-10-18): Osobní údaje on the left — the photo beside the name fields and
 * the e-mail, stacked — and Heslo over Dvoufázové ověření on the right, the left card as tall as the two. The breakpoints read the page's own width (a container
 * query), so the sidebar's state counts; below them every card stacks and every row folds to one column. */
.profile { container-type: inline-size; }
.profile-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.profile-card { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.profile-card__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2) var(--space-3); }
.profile-card__head > h2 { margin: 0; color: var(--text-1); }
/* The heading's free end: a state tag, and a confirmation that appears there and fades rather than entering the card. */
.profile-card__aside { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2) var(--space-3); min-width: 0; }
.profile-card .toolbar { margin: 0; }
.profile-card__act { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.profile-card__act > p { margin: 0; }
.profile-form { display: flex; flex-direction: column; gap: var(--space-4); }
.profile-form__row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
.profile-identity { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
.profile-identity__fields { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.profile-photo { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); }
.profile-photo__avatar { position: relative; display: inline-flex; border-radius: var(--radius-lg); }
.profile-photo__avatar > .avatar { transition: transform var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard); }
/* An image dragged over the avatar lifts it: the drop target says it will take the file. */
.profile-photo__avatar[data-dragging="true"] > .avatar { transform: scale(1.04); box-shadow: var(--elev-2); }
.profile-identity .profile-form__row { grid-template-columns: minmax(0, 1fr); }
.profile-email { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.profile-email__value { margin: 0; color: var(--text-1); overflow-wrap: anywhere; }
@container (min-width: 420px) {
  .profile-identity { grid-template-columns: auto minmax(0, 1fr); align-items: start; }
}
@container (min-width: 760px) {
  .profile-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .profile-grid > #profile-identity { grid-row: span 2; align-self: stretch; }
}
@media (max-width: 639px) { .profile-card { padding: var(--space-4); } }

/* == layout: the landing of an administrator assigned to no customer == */
.landing { display: flex; flex-direction: column; gap: var(--space-4); }
.landing > * { margin: 0; }
.landing__icon { color: var(--text-3); display: inline-flex; }
.landing > h1:focus { outline: none; }
.landing .toolbar { margin: var(--space-2) 0 0; }

/* == reduced motion: the sidebar's state changes land at once ==
 * The duration tokens already fall to 0 (base.css); the header's crossfade also waits by a delay, which would still
 * hold the brand and the logo back — so the delays go too. The logo↔icon swap remains, as a state change. */
@media (prefers-reduced-motion: reduce) {
  .sidebar, .sidebar * { transition-delay: 0ms !important; }
}
/* The authenticator's replacement reuses the pre-authentication fields; on this page they keep the form width of
 * the fields around them. */
.profile .field { max-width: var(--field-max); }
.preauth__title + form { margin-top: var(--space-4); }

/* == layout: panel sections and the danger zone (client.views.course, client.views.customer.settings) == */
.panel { --holder: var(--surface); --holder-below: var(--bg); padding: var(--card-pad); background-color: var(--surface); border-radius: var(--radius-lg); box-shadow: var(--elev-1); }
.section-gap { margin-top: var(--card-gap); }
/* The danger zone keeps the page's card gap; its own heading communicates the distinct consequence. */
.danger-zone { margin-top: var(--card-gap); }
.danger-zone .field-note { margin-bottom: var(--space-4); }

/* == layout: the console's Customers and Courses lists (client.views.customers, client.views.courses) ==
 * The creation slot is the card's first row. It needs no rule under it: the table header below is a half-step fill,
 * and the slot's own surface and 44 px rhythm set it apart. */
.operator-list__create { min-height: 44px; }
.operator-list__create .inline-create { min-height: 44px; }
.operator-list__customer { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.operator-list tr.is-new td { background: var(--accent-tint); }

/* == layout: the course screen (client.views.course) == */
.course-heading { margin-bottom: var(--space-6); }
.course-heading .page-header__meta { display: block; -webkit-line-clamp: unset; overflow: visible; }
.course-heading__meta { display: inline-flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
.course-heading__unavailable, .course-delete-unavailable { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2) var(--space-3); }
.course-heading .disabled-reason, .course-delete-unavailable .disabled-reason { margin: 0; }
.course-modules { padding-left: var(--space-6); }
/* The entitlement rows are set apart by the list's gap and their own padding, never by a rule. */
.entitlement-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) 0; }
.entitlement-identity { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.entitlement-name { color: var(--text-1); text-decoration: none; }
/* The customer's monogram tile; the view paints it in the customer's primary colour. */
.entitlement-glyph {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: var(--surface-2);
  color: var(--text-1);
  font: var(--weight-semibold) var(--text-16) / 1 var(--font-sans);
}
@media (max-width: 639px) {
  .entitlement-row { flex-wrap: wrap; }
  .entitlement-row > .btn { margin-left: auto; }
}
/* == layout: a partner's home organisation (client.views.partners/home-section) ==
 * The select at a single field's width and its removal beside it, on the well's bottom line; on a phone the field
 * takes the row and the removal wraps under it at the end. */
.home-designation { display: flex; align-items: flex-end; flex-wrap: wrap; gap: var(--space-3); }
.home-designation > .form-field { flex: 0 1 400px; min-width: 0; }
@media (max-width: 639px) {
  .home-designation > .form-field { flex-basis: 100%; }
  .home-designation > .btn { margin-left: auto; }
}
/* == layout: a list's filter card and results bar (client.ui.table/filter-card, results-bar) ==
 * Every filter of a list in one raised card between the page and the table card, with the table card's surface,
 * level, radius and holder: an optional lead line (the list's state selection); the head — the search across the
 * card, the card's acts at its end on the well's bottom line (the "Další filtry" disclosure, the reset); the primary
 * fields in equal columns; and the disclosed secondary fields under them in the same columns. The results bar follows
 * the card: what the list's acts will hold at its start, the acts at its end, apart from the filters. */
.filter-card { --holder: var(--surface); --holder-below: var(--bg); display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--card-gap); padding: var(--space-3) var(--space-4) var(--space-4); background-color: var(--surface); border-radius: var(--radius-lg); box-shadow: var(--elev-1); }
/* The lead line is a container, so what it holds (the Runs state filter) reflows by the card's width. */
.filter-card__lead { container: filter-lead / inline-size; }
.filter-card__head { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3) var(--space-4); }
.filter-card__search { flex: 1 1 320px; min-width: 0; }
.filter-card__search > * { max-width: none; }
.filter-card .search-field { width: 100%; }
.filter-card__fields, .filter-card__more { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); align-items: start; gap: var(--space-3) var(--space-4); min-width: 0; }
.filter-card__more[hidden] { display: none; }
.filter-card__fields:empty { display: none; }
.filter-card__fields > .form-field, .filter-card__more > .form-field { min-width: 0; max-width: none; margin: 0; }
.filter-card__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-inline-start: auto; min-height: var(--control-h); }
.filter-card__note { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); flex-basis: 100%; margin: 0; color: var(--text-2); font: var(--type-small); }
.results-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); margin-bottom: var(--space-3); }
.results-bar__summary { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); flex: 1 1 240px; min-width: 0; }
.results-bar__scope { color: var(--text-3); font: var(--type-small); font-variant-numeric: tabular-nums; }
.results-bar__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); margin-inline-start: auto; }
@media (max-width: 639px) {
  .filter-card { padding: var(--space-3); }
  .filter-card__fields, .filter-card__more { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .filter-card__actions { width: 100%; margin-inline-start: 0; justify-content: space-between; }
  .results-bar__actions { width: 100%; justify-content: stretch; }
  .results-bar__actions > .btn { flex: 1 1 0; }
}

/* == layout: the Employees view (client.views.customer.employees) == */
/* Scrolled to after a page change; the margin keeps its top clear of the phone's sticky top bar. */
.employees { scroll-margin-top: 72px; }
.employees > .status-slot:empty { display: none; }
/* The selection status: how many are selected, or how to select; its line is the enrolment button's disabled reason. */
.selection-status { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); min-height: 32px; }
/* With nothing visible to say (the count and the acts are the docked bar's), the line keeps its place for focus and
 * assistive technology but takes no room in the results bar. */
.selection-status--quiet { position: absolute; min-height: 0; }
.selection-status__line { margin: 0; max-width: 420px; color: var(--text-2); font: var(--type-small); font-variant-numeric: tabular-nums; }
/* The phone list's select-all stands above the items, as the table header's does above the rows. */
.employees-select-page { padding: var(--space-2) var(--space-4) 0; }
.employee-email { display: block; max-width: 260px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--text-2); }
.employee-email-inline { display: none; }
/* The phone item's results: the success rate and the items to practise, one line. */
.employee-results-line { display: flex; flex-wrap: wrap; gap: 0 var(--space-3); margin: var(--space-2) 0 0; color: var(--text-2); font: var(--type-small); }
@media (min-width: 640px) and (max-width: 1023px) { .employee-email-inline { display: block; } }
.employee-no-course, .employee-no-tag { color: var(--text-3); font: var(--type-small); }
/* Employee tags (ADR-0062). On an employee's page one line under the editable fields: the heading, the tags as neutral
 * tags, then "Spravovat štítky" — never an × on a tag. The selection bar holds the same act. Its popover is one tag
 * picker: the customer's tags as one dropdown of checkable options ending in "Vytvořit štítek", which opens a name
 * field with "Vytvořit" under it. The import's preview holds the same picker. The tags view opens with one lead sentence in small `text-2` above its table card. */
.employee-tags { margin: var(--space-6) 0 var(--space-10); }
.employee-tags__line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.employee-tags__title { margin: 0; font: var(--type-title-2); }
.employee-tags__acts { display: flex; align-items: center; gap: var(--space-2); }
.tag-picker { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.tag-picker__create { display: flex; align-items: flex-end; gap: var(--space-2); }
.tag-picker__create > :first-child { flex: 1 1 auto; min-width: 0; }
.tag-outcomes { display: flex; flex-direction: column; gap: var(--space-3); }
.tag-outcomes__tag { display: flex; flex-direction: column; gap: var(--space-1); }
.employee-tags-view .section-lead { margin: 0 0 var(--space-3); max-width: 680px; color: var(--text-2); font: var(--type-small); }
.data-table .data-table__name:focus-visible { outline-offset: 2px; border-radius: var(--radius-xs); }
.course-labels__more-toggle {
  border: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-2);
  font: var(--type-caption);
  letter-spacing: var(--track-caption);
  font-variant-numeric: tabular-nums;
  text-decoration: none;
}
@media (hover: hover) { .course-labels__more-toggle:hover { background: var(--surface-3); color: var(--text-1); } }
@media (max-width: 639px) {
  .employee-email { max-width: none; }
}
@media (min-width: 640px) { .employees-select-page { display: none; } }

/* == layout: the Employees page's two bulk-act popovers (client.views.enrolment, client.views.employee-import) ==
 * Each is an overlay card anchored to its toolbar button; the card is the overlay's own surface and holds nothing
 * framed — sections are told apart by space and type, the drop zone and the totals by a fill. A card taller than the
 * room the overlay layer gives it scrolls inside itself, the one inner scroller here, so the page behind the modal
 * popover never has to. */
.overlay--popover:has(> .overlay__body .bulk-card) { display: flex; flex-direction: column; }
.overlay--popover:has(> .overlay__body .bulk-card) .overlay__dialog { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.bulk-card { display: flex; flex-direction: column; gap: var(--space-3); min-height: 0; }
/* A flow popover (rulebook §9): the head — the title, and the cross pulled into the card's corner — then the fields,
 * then the foot, the card's one act at its end edge. The card's padding is the one inset on every side; nothing inside
 * reserves a gutter of its own, so the content meets the same margin left and right. */
.bulk-card__head { display: flex; align-items: flex-start; gap: var(--space-2); margin: calc(-1 * var(--space-1)) calc(-1 * var(--space-1)) 0 0; }
.bulk-card__head > .bulk-card__title { flex: 1 1 auto; min-width: 0; padding-top: var(--space-1); }
.bulk-card__head > .icon-btn { flex: none; }
/* The compact popovers (tempo, enrolment, tags, language): narrower and tighter than the overlay's default card. */
.overlay--popover:not(.overlay--wide):has(> .overlay__body .bulk-card__head) { width: min(360px, calc(100vw - 16px)); min-width: 280px; padding: var(--space-4); }
.overlay--popover:has(> .overlay__body .bulk-card__head) { padding: var(--space-4); }
.overlay--popover:has(> .overlay__body .bulk-card__head) .bulk-card { gap: var(--space-4); }
.overlay--popover:has(> .overlay__body .bulk-card__head) .bulk-card__section { gap: var(--space-4); }
.bulk-card > .bulk-card__actions { padding-top: var(--space-1); }
.language-choice { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
/* The import card never scrolls as a whole: its title stays, and each stage scrolls inside itself — the preview's body
 * alone, between the title and its pinned footer, so the scrollbar belongs to the content it moves. */
.bulk-card--import { overflow: hidden; }
.bulk-card--import > .bulk-card__section { overflow-y: auto; overscroll-behavior: contain; min-height: 0; }
.import-step { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.import-step__body { display: flex; flex-direction: column; gap: var(--space-5); min-height: 0; flex: 1 1 auto; }
.import-step__group { display: flex; flex-direction: column; gap: var(--space-3); }
.import-step__head { display: flex; align-items: center; gap: var(--space-1); min-width: 0; }
.import-step__head > .bulk-card__meta { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.import-step__edit { margin-left: auto; padding: 0 0 1px; border: 0; background-color: transparent; cursor: pointer; white-space: nowrap; font: var(--type-label); }
.import-step__table { display: flex; flex-direction: column; gap: var(--space-2); }
.import-step__filter { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.import-step__footer { display: flex; flex-direction: column; gap: var(--space-3); flex: none; padding-top: var(--space-4); }
.import-step__footer .bulk-card__summary p { color: var(--text-2); font: var(--type-small); }
.import-step__footer .bulk-card__actions { justify-content: space-between; }
.bulk-card__title { margin: 0; color: var(--text-1); font: var(--type-title-2); }
.bulk-card__subtitle { margin: 0; color: var(--text-1); font: var(--type-title-3); }
.bulk-card__section { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.bulk-card__line { display: flex; align-items: center; gap: var(--space-2); margin: 0; color: var(--text-1); overflow-wrap: anywhere; }
.bulk-card__meta { margin: 0; color: var(--text-2); font: var(--type-small); overflow-wrap: anywhere; }
.bulk-card__summary { display: flex; flex-direction: column; gap: var(--space-1); }
.bulk-card__summary p { margin: 0; color: var(--text-1); overflow-wrap: anywhere; }
.bulk-card__course { font-weight: var(--weight-medium); }
.bulk-card__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); }
.enrol-course { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.enrol-tempo .form-field__help { margin: var(--space-1) 0 0; }
/* The drop zone: a filled region on the card, never a dashed frame. */
/* The drop zone is ONE control — a label for the hidden file input, marked as the input well it is
 * (`data-focus="well"`), so its rest, hover, pressed and invalid states are the recessed input's own. It also sinks
 * as a focused input does while its hidden input has keyboard focus, and further, toward the accent, while a file is
 * dragged over it — never with a ring or a line. A chosen file's name takes the instruction's place. */
.import-drop {
  --holder: var(--surface-overlay);
  --holder-below: var(--overlay-below);
  display: flex; align-items: center; gap: var(--space-3);
  min-height: 72px; padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  cursor: pointer;
}
.import-drop[data-focus="well"]:focus-within { background-color: var(--field-focus); box-shadow: var(--inset-focus); }
.import-drop[data-focus="well"][data-dragging] { background-color: color-mix(in srgb, var(--field-focus) 88%, var(--accent)); box-shadow: var(--inset-focus); }
.import-drop__icon { display: inline-flex; flex: none; color: var(--text-2); transition: color var(--dur-fast) var(--ease-standard); }
.import-drop:is(:hover, :focus-within, [data-dragging]) .import-drop__icon { color: var(--accent); }
.import-drop[data-file] .import-drop__icon { color: var(--status-on-track-fg); }
.import-drop[data-invalid="true"] .import-drop__icon { color: var(--destructive-fg); }
.import-drop__text { display: flex; flex-direction: column; min-width: 0; }
.import-drop__lead { color: var(--text-1); font: var(--type-body-strong); }
.import-drop__file { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.import-drop__meta { color: var(--text-2); font: var(--type-small); }
.import-card__delimiter { display: flex; flex-direction: column; gap: var(--space-3); }
.import-card__spinner { display: inline-flex; }
@media (prefers-reduced-motion: no-preference) { .import-card__spinner svg { animation: btn-spin var(--dur-spin) var(--ease-linear) infinite; } }
/* The file's headers as the server read them, in the technical face: mojibake and a wrong delimiter show here. */
.import-card__headers { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-2); margin: 0; padding: 0; list-style: none; }
.import-card__headers li { padding: 2px var(--space-2); border-radius: var(--radius-xs); background-color: var(--surface-overlay-hover); color: var(--text-1); font: var(--type-small); font-family: var(--font-mono); overflow-wrap: anywhere; }
/* The mapping as a two-column table without rules: the file's header in the technical face, then what it becomes. */
.import-mapping { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: var(--space-2) var(--space-4); }
.import-mapping__caption { color: var(--text-2); font: var(--type-caption); letter-spacing: var(--track-caption); }
.import-mapping__header { min-width: 0; overflow: hidden; color: var(--text-1); font: var(--type-mono); text-overflow: ellipsis; white-space: nowrap; }
.import-mapping__column { min-width: 0; }
.import-mapping__column > .form-field { max-width: none; }
/* The totals as one row of compact figure chips: the figure first, its word after, on the overlay's hover fill. */
.import-totals { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; }
.import-totals__item { display: flex; flex-direction: row-reverse; align-items: baseline; gap: var(--space-1); padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm); background-color: var(--surface-overlay-hover); }
.import-totals__item dt { color: var(--text-2); font: var(--type-small); }
.import-totals__item dd { margin: 0; color: var(--text-1); font: var(--weight-semibold) var(--text-13) / var(--lh-13) var(--font-sans); font-variant-numeric: tabular-nums; }
.import-preview .data-table { width: 100%; }
.import-preview__name, .import-preview__email { display: block; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.import-preview .data-table th, .import-preview .data-table td { --holder: var(--surface-overlay); }
.import-pager { padding: 0; }
/* The enrolment: the checkbox with its help tip, then — once chosen — the course and the tempo side by side, the tempo's
 * radios in one row. */
.import-enrol { display: flex; flex-direction: column; gap: var(--space-3); }
.import-enrol__toggle { display: flex; align-items: center; gap: var(--space-1); }
/* What a ticked option opens, under its checkbox and lined up with the checkbox's label: one column, the fields
 * 16 px apart as every form's, no wider than a form's single field needs. */
.import-enrol__fields { display: flex; flex-direction: column; gap: var(--space-4); max-width: 440px; padding-left: var(--space-6); }
.import-card__confirm { display: flex; flex-direction: column; gap: var(--space-3); }
.import-card__enrolment, .import-card__tags { display: flex; flex-direction: column; gap: var(--space-3); }
@media (max-width: 639px) {
  .bulk-card__actions { justify-content: stretch; }
  .bulk-card__actions > .btn { flex: 1 1 auto; }
  .import-enrol__fields { padding-left: 0; max-width: none; }
}

/* == layout: employee detail (client.views.employee, client.views.certificates, client.views.delivery-evidence) ==
 * The person first, then the evidence: the profile card, the course cards, the selected run's results card, the
 * certificates card, the simulations and, last, the delivery summary with its table behind a disclosure. The page
 * and its detail are page stacks (the page rhythm: one card gap, content cards at the card padding), cards at J1 on
 * the page ground, nothing framed. Every card is a container and reflows by its own width, never the viewport's. */
.employee-page .panel { container: employee-card / inline-size; min-width: 0; }

/* The disclosure (client.ui.disclosure): text that opens secondary facts, a chevron turning beside it. Its only
 * callers are on this page; its rules move to the components stylesheet when a second page uses it. */
.disclosure > summary { --dash-bottom: 2px; display: inline-flex; align-items: center; gap: var(--space-2); width: fit-content; padding: var(--space-2) 0; list-style: none; color: var(--text-2); font: var(--type-body-strong); }
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure__chevron { display: inline-flex; transform: rotate(-90deg); transition: transform var(--dur-fast) var(--ease-standard); }
.disclosure[open] > summary .disclosure__chevron { transform: none; }
.disclosure[open] > summary { color: var(--text-1); }
.disclosure > :not(summary) { margin-top: var(--space-2); }

/* The profile card: the avatar beside the name, contact, state and actions; the tags under them; the fields behind
 * "Upravit údaje". */
.employee-profile { display: flex; flex-direction: column; gap: var(--space-4); }
.person-header { display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.person-header .page-header { margin-bottom: 0; }
.person-header .page-header__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); -webkit-line-clamp: unset; overflow: visible; }
.contact-line { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-4); min-width: 0; }
.contact-link { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; color: var(--link); text-decoration: none; }
.contact-link > svg { flex: none; }
/* A long address stays one line and ellipsises (the whole of it is in the link's name and its mailto:), so the two
 * contact actions keep their place on a narrow card instead of wrapping over several lines. */
.contact-link > span { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
@media (pointer: coarse) { .contact-link { min-height: 44px; } }
.contact-fact { color: var(--text-2); }
.employee-profile .employee-tags { margin: 0; }
.employee-profile .employee-tags__title { font: var(--type-body-strong); color: var(--text-2); }
.employee-edit__fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: var(--space-4); padding-top: var(--space-2); }
.employee-edit .autosave { margin-top: var(--space-3); }
@container employee-card (max-width: 559px) {
  .person-header { grid-template-columns: 40px minmax(0, 1fr); gap: var(--space-3); }
  .person-header .avatar--48 { width: 40px; height: 40px; }
  .person-header .page-header { grid-template-columns: minmax(0, 1fr); }
  .person-header .page-header__actions { justify-content: flex-start; }
  .contact-line { display: flex; width: 100%; }
}

/* The course cards: as many across as fit at 360 px or more, each the wide course label, one line of facts and its
 * acts at the foot. The run whose results are shown below says so in words where the others offer the way there. */
.employee-runs { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr)); gap: var(--card-gap); list-style: none; margin: 0; padding: 0; }
.employee-run { display: flex; flex-direction: column; gap: var(--space-3); }
.employee-run > .course-labels { margin: 0; }
.employee-run__facts { display: flex; flex-wrap: wrap; align-items: center; margin: 0; color: var(--text-2); font: var(--type-small); font-variant-numeric: tabular-nums; }
.employee-run__sep { color: var(--text-3); padding: 0 6px; }
.employee-run__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); margin-top: auto; }
.employee-run__results { font: var(--type-body-strong); }
.employee-run__current { color: var(--text-3); font: var(--type-small); }

/* The results card: the run named with its two parts, a row of figures, the module list, then the disclosures. */
.employee-results { display: flex; flex-direction: column; gap: var(--space-5); }
.employee-results__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-2) var(--space-6); }
.employee-results__run { margin: 0; color: var(--text-1); font: var(--type-body-strong); }
.employee-results__nav { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); margin: 0; }
.employee-results__nav > [aria-current] { color: var(--text-1); font-weight: var(--weight-medium); }
.employee-results__body, .employee-history { display: flex; flex-direction: column; gap: var(--space-5); }
.employee-results__subtitle { margin: 0 0 var(--space-2); color: var(--text-1); font: var(--type-title-3); }
.employee-results p { margin: 0; }

/* The figures: label over figure over the server's ratio as a 6 px meter, as many across as fit at 160 px. */
.employee-figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)); gap: var(--space-5) var(--space-6); margin: 0; }
.employee-figure { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.employee-figure dd { margin: 0; }
.employee-figure__label { color: var(--text-2); font: var(--type-label); }
.employee-figure__value { color: var(--text-1); font: var(--type-title-1); font-variant-numeric: tabular-nums; }
.employee-figure__meter { height: 6px; border-radius: var(--radius-xs); background: var(--surface-2); overflow: hidden; }
.employee-figure__meter > span { display: block; height: 100%; border-radius: var(--radius-xs); background: var(--chart-series-1); }
.employee-figure__note { color: var(--text-3); font: var(--type-small); }
.employee-figures__note { margin: calc(-1 * var(--space-2)) 0 0; color: var(--text-3); font: var(--type-small); }
/* A success rate in its band (client.ui.learning-report/success-rate): green from 80 %, yellow from 50 %, red below. */
.success-rate { font-weight: var(--weight-medium); font-variant-numeric: tabular-nums; white-space: nowrap; }
.success-rate[data-band="on-track"] { color: var(--status-on-track-fg); }
.success-rate[data-band="behind"] { color: var(--status-behind-fg); }
.success-rate[data-band="serious"] { color: var(--status-serious-fg); }
/* The success rate in its band: green from 80 %, yellow from 50 %, red below — the value and its meter. */
.employee-figure[data-band="on-track"] { --band-fg: var(--status-on-track-fg); --band-solid: var(--status-on-track-solid); }
.employee-figure[data-band="behind"] { --band-fg: var(--status-behind-fg); --band-solid: var(--status-behind-solid); }
.employee-figure[data-band="serious"] { --band-fg: var(--status-serious-fg); --band-solid: var(--status-serious-solid); }
.employee-figure[data-band] .employee-figure__value { color: var(--band-fg); }
.employee-figure[data-band] .employee-figure__meter > span { background: var(--band-solid); }

/* The module list: one line per module — the name leading to its items, its facts at the end — parted by rhythm. */
.employee-modules__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.employee-module { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-1) var(--space-4); min-height: 36px; padding: var(--space-2) 0; }
.employee-module__name { min-width: 0; color: var(--text-1); font: var(--type-body-strong); text-decoration: none; overflow-wrap: anywhere; }
.employee-module__name[aria-current] { color: var(--link); }
.employee-module__facts { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); color: var(--text-2); font: var(--type-small); font-variant-numeric: tabular-nums; }
.employee-module-detail { display: flex; flex-direction: column; gap: var(--space-3); }

/* Label and value lines behind a disclosure: every metric, the technical identifiers, a certificate's facts. */
.employee-metrics, .certificate-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: var(--space-2) var(--space-6); margin: 0; }
.employee-metrics__row, .certificate-facts__row { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.employee-metrics dt, .certificate-facts dt { color: var(--text-2); font: var(--type-small); }
.employee-metrics dd, .certificate-facts dd { margin: 0; color: var(--text-1); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.employee-metrics__coverage { display: block; color: var(--text-3); font: var(--type-small); }
.employee-identifier, .certificate-facts__identifier { font-family: var(--font-mono); }

/* The certificates card: one row per certificate — the course and its state tag over one line of when and which,
 * and at the row's end its PDF and, for a superadmin, the menu; for a revoked one what the revocation leaves
 * standing. Rows part by their rhythm, never by a rule. */
.certificate-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-5); }
.certificate-item { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2) var(--space-4); min-width: 0; }
.certificate-item__main { display: flex; flex-direction: column; gap: var(--space-1); flex: 1 1 280px; min-width: 0; }
.certificate-item__title { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.certificate-item__course { color: var(--text-1); font: var(--type-body-strong); overflow-wrap: anywhere; }
.certificate-item__acts { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }
.certificate-item__when, .certificate-item__note { margin: 0; color: var(--text-2); font: var(--type-small); }
.certificate-item__note { color: var(--text-1); }
.employee-certificates__empty, .delivery-card__empty, .employee-runs__empty { margin: 0; color: var(--text-2); }

/* The delivery summary: the introduction, then the count, the outcomes as tags with their counts, and the latest
 * attempt, as many across as fit; the full table opens beneath the card. */
.delivery-evidence { display: flex; flex-direction: column; gap: var(--space-3); }
.delivery-card { display: flex; flex-direction: column; gap: var(--space-4); }
.delivery-card__intro { margin: 0; max-width: var(--reading-max); color: var(--text-2); font: var(--type-small); }
.delivery-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: var(--space-4) var(--space-6); margin: 0; }
.delivery-summary__item { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.delivery-summary__item > dt { color: var(--text-2); font: var(--type-label); }
.delivery-summary__item > dd { margin: 0; color: var(--text-1); font-variant-numeric: tabular-nums; }
.delivery-summary__figure { font: var(--type-title-1); }
.delivery-summary__outcomes { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); }
.delivery-summary__outcome { display: inline-flex; align-items: center; gap: var(--space-2); }
.delivery-summary__count { font-variant-numeric: tabular-nums; }
.delivery-evidence .t-mono { font-family: var(--font-mono); }

/* The timeline: round markers on one line, the dates in a right-aligned column, flush in the results card that holds
 * it. The rendering of its entries is the timeline's own; only its frame is drawn here. */
.run-timeline { position: relative; list-style: none; margin: 0; padding: 0; }
.run-timeline::before { content: ""; position: absolute; left: 147.5px; top: 14px; bottom: 14px; width: 1px; background: var(--chart-grid); }
.run-timeline li { position: relative; display: grid; grid-template-columns: 136px 24px minmax(0, 1fr); align-items: center; padding: 6px 0; color: var(--text-1); }
.run-timeline li::before { content: ""; grid-column: 2; grid-row: 1; justify-self: center; width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--chart-baseline); box-shadow: 0 0 0 3px var(--surface); }
.run-timeline li > span { grid-column: 3; grid-row: 1; min-width: 0; overflow-wrap: anywhere; }
.run-timeline time { grid-column: 1; grid-row: 1; text-align: right; color: var(--text-2); font: var(--type-small); font-variant-numeric: tabular-nums; }
.run-timeline__module { color: var(--text-2); }
.run-timeline__icon { display: inline-flex; vertical-align: -2px; margin-right: 6px; }
.run-timeline li.is-automated > span { color: var(--text-3); font: var(--type-small); }
.run-timeline li.is-automated .run-timeline__module { color: var(--text-3); }
@container employee-card (max-width: 479px) {
  .run-timeline::before { left: 95.5px; }
  .run-timeline li { grid-template-columns: 84px 24px minmax(0, 1fr); align-items: start; }
  .run-timeline li::before { margin-top: 5px; }
}


/* == layout: runs (client.views.runs) == */
/* The state filter heads the shared filter card (client.ui.table/filter-card): a segmented control where the card's
 * lead line holds all six states, the same filter as a select where it does not — by the card's own width, never
 * the viewport's. */
.runs-filter__select { display: none; }
@container filter-lead (max-width: 599px) {
  .runs-filter__segmented { display: none; }
  .runs-filter__select { display: block; }
  .runs-filter__select .form-field { max-width: 320px; margin: 0; }
}
.runs-attention { display: block; margin-top: var(--space-1); color: var(--text-2); font: var(--type-small); }
.runs-date { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--text-2); }
.tempo-mark { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.tempo-mark__icon { display: inline-flex; color: var(--text-2); }
.runs .list-item__extra { display: flex; flex-direction: column; gap: var(--space-1); }
.runs .list-item__primary > .check { min-height: 0; }
/* A run no transition applies to has no checkbox; its gutter keeps its name aligned with the others. */
.check-gutter { display: inline-block; width: 16px; flex: none; }
/* The person column is capped so the course column takes the width: long names and addresses ellipsise. */
.runs .runs-person { width: 240px; max-width: 240px; }
.runs .runs-person > .data-table__name,
.runs .runs-person > .data-table__secondary { display: block; max-width: 216px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.runs .runs-course { width: 100%; }

/* Choice lists (client.ui.choice, and the course screen's entitlement rows): one choice is a raised card, selected by
 * its fill; rows are told apart by their rhythm. */
.choice-list { display: flex; flex-direction: column; gap: var(--space-2); }
.choice {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: 56px;
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
  color: var(--text-1);
  font: var(--type-body-strong);
  text-align: left;
  cursor: pointer;
}
.choice > .muted { color: var(--text-2); font-weight: var(--weight-regular); font-size: var(--text-13); white-space: nowrap; }
@media (hover: hover) { .choice:hover { background: var(--surface-2); } }
.choice.is-selected { background: var(--accent-tint); }
.choice-row { display: flex; align-items: center; gap: var(--space-3); min-height: 44px; padding: var(--space-2) var(--space-4); cursor: pointer; }
.choice-row .muted { margin-left: auto; font-size: var(--text-13); color: var(--text-2); overflow-wrap: anywhere; text-align: right; }
@media (hover: hover) { .choice-row:hover { background: var(--surface-2); } }

.overview-section { margin-top: var(--card-gap); }
.overview-reason { color: var(--text-2); }

/* == layout: a customer destination still loading == */
.customer-loading > .skeleton--title { display: block; height: 32px; width: 200px; margin-bottom: var(--card-gap); }
.report-activity__quiet { color: var(--text-2); }
.report-activity__quiet > summary { --dash-bottom: 2px; width: fit-content; cursor: pointer; padding: var(--space-2) 0; color: var(--text-1); font: var(--type-body-strong); }
.report-activity__quiet-list { margin: 0; padding: 0 0 0 var(--space-4); display: flex; flex-direction: column; gap: var(--space-1); }
.report-activity__course { color: var(--text-1); }
/* A row's module stands on the card's surface like any cell — no header fill down the column — with its course under
 * it; the three counts are the figures, tabular. */
.report-activity .data-table th[scope="row"] { background-color: transparent; }
.report-activity__module { display: block; color: var(--text-1); }
.report-activity .data-table td { font-variant-numeric: tabular-nums; }
.responsive-table + .report-activity__quiet { margin-top: var(--space-2); }
/* The import's format hint: the recognised headers and a sample, in the technical face (rulebook §7). */
/* What a file should look like, quiet beneath the drop zone: the headers as one row of chips (the required one marked),
 * the limits behind the title's help, and the sample small and low in emphasis. */
.import-format { display: flex; flex-direction: column; gap: var(--space-2); }
.import-format p { margin: 0; }
.import-format__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); min-height: 32px; }
.import-format__title { color: var(--text-2); font: var(--type-caption); letter-spacing: var(--track-caption); }
.import-format__columns { display: flex; flex-wrap: wrap; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.import-format__column { padding: 2px var(--space-2); border-radius: var(--radius-xs); background-color: var(--surface-overlay-hover); color: var(--text-1); font: var(--type-small); font-family: var(--font-mono); }
.import-format__required { margin-left: 2px; color: var(--destructive-fg); }
.import-format__sample { margin: var(--space-2) 0 0; padding: 0; background: transparent; color: inherit; font: var(--type-small); font-family: var(--font-mono); white-space: pre-wrap; overflow-wrap: anywhere; user-select: all; }

/* == layout: the operator console's Overview (client.views.overview) ==
 * Its tiles are the shared stat grid; its list of customers with stalled runs names each by its mark and name. */
.overview-customer { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }

/* == layout: the phishing placeholder in Settings (client.views.phishing) ==
 * Simulations are not operational yet (operator 2026-10-18): one quiet line, its mark and a state tag, nothing to act on. */
.settings-phishing__line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: 0; color: var(--text-2); }
.settings-phishing__icon { display: inline-flex; color: var(--text-3); }

/* Printing restores the document flow the fixed content card replaces on screen, so a long page prints whole. */
@media print {
  .app--sidebar, .app--sidebar .app__column { height: auto; overflow: visible; transform: none; box-shadow: none; }
}

/* == layout: the customer's readiness to send (client.views.customer.readiness, ADR-0063) ==
 * Settings open with the launch checklist (redesigned 2026-10-18): a header — the title, five progress segments with
 * their count, and the launch at the end — one status line, then the conditions as compact rows, two to a line where
 * the card is wide. A met row is quiet (muted, a check on the accent tint); the row to do now carries the accent tint
 * and its act; the technical guidance waits behind a disclosure. Once launched, one line stands in its place. */
.customer-page > .notice { margin-bottom: var(--space-6); }
.readiness { container-type: inline-size; }
/* Until launch the checklist is the page's objective: one rung up from the cards around it, and its foot holds the
 * launch, the page's one large primary act (operator 2026-10-18). */
.page-stack > .readiness { box-shadow: var(--elev-2); }
.readiness__launch-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-5); margin-top: var(--space-6); }
.readiness__launch-text { flex: 1 1 16rem; margin: 0; color: var(--text-2); font: var(--type-body); }
.readiness__launch-line > .status-line, .readiness__launch-line > .notice { flex-basis: 100%; }
.readiness > .status-line, .readiness > .notice { margin-bottom: var(--space-3); }
.readiness__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-5); }
.readiness__head > h2 { margin: 0; color: var(--text-1); }
.readiness__progress { display: inline-flex; align-items: center; gap: var(--space-2); }
.readiness__segments { display: inline-flex; gap: 3px; }
.readiness__segments > span { width: 24px; height: 6px; border-radius: var(--radius-full); background-color: var(--surface-3); }
.readiness__segments > span.is-met { background-color: var(--accent); }
.readiness__count { color: var(--text-2); font: var(--type-label); font-variant-numeric: tabular-nums; }
.readiness__launch { margin-left: auto; }
.readiness__status { margin: var(--space-2) 0 var(--space-4); color: var(--text-2); font: var(--type-small); min-height: var(--lh-13); }
.readiness__columns { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2); align-items: start; }
.readiness__list { display: flex; flex-direction: column; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
/* Two columns, each read top to bottom, only where a row still holds its words and its act side by side. */
@container (min-width: 840px) { .readiness__columns { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2) var(--space-4); } }
.readiness-row {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--space-1) var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-md);
}
.readiness-row--next { background-color: var(--accent-tint); }
.readiness-row__marker {
  position: relative; display: grid; place-items: center; width: 24px; height: 24px; border-radius: var(--radius-sm);
  background-color: var(--surface-hover); color: var(--text-2);
  font: var(--weight-medium) var(--text-12) / 1 var(--font-sans); font-variant-numeric: tabular-nums;
}
.readiness-row--met .readiness-row__marker { background-color: var(--accent-tint); color: var(--accent); }
/* The markers are the learner's module markers: a number in a 6 px rounded square. A met step keeps its number;
 * the completion badge stands over the marker's upper-right corner (J1), as on a learner's finished module. */
.readiness-row__badge { position: absolute; top: -8px; right: -11px; --badge-disc: var(--surface); color: var(--status-on-track-fg); border-radius: var(--radius-full); box-shadow: var(--elev-1); }
.readiness-row--next .readiness-row__marker { background-color: var(--accent); color: var(--accent-ink); }
.readiness-row__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* The title's first line centres on the 24 px marker by padding, so a wrapped title keeps the role's 20 px lines. */
.readiness-row__title { margin: 0; padding-block: calc((24px - var(--lh-14)) / 2); color: var(--text-1); font: var(--type-name); }
.readiness-row--met .readiness-row__title { color: var(--text-2); font-weight: var(--weight-medium); }
.readiness-row__detail { margin: 0; color: var(--text-2); font: var(--type-small); overflow-wrap: anywhere; }
.readiness-row--met .readiness-row__detail { color: var(--text-3); }
.readiness-row__latest { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); font-variant-numeric: tabular-nums; }
.readiness-row__acts { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); }
.readiness-row__acts .disabled-reason { flex-basis: 100%; margin: 0; text-align: right; }
@container (max-width: 639px) {
  .readiness-row { grid-template-columns: 24px minmax(0, 1fr); }
  .readiness-row__acts { grid-column: 2; justify-content: flex-start; }
  .readiness-row__acts .disabled-reason { text-align: left; }
  .readiness__launch { margin-left: 0; flex-basis: 100%; }
  .readiness__launch-line > .btn { flex: 1 1 100%; }
}
.readiness-guidance { margin-top: var(--space-2); }
.readiness-guidance__summary { cursor: pointer; color: var(--text-2); font: var(--type-label); }
.readiness-guidance[open] > :not(summary) { margin-top: var(--space-3); }
.readiness-guidance__lead { margin: 0; color: var(--text-2); font: var(--type-small); }
.readiness-guidance__facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); align-items: center; gap: var(--space-1) var(--space-4); margin: 0; }
.readiness-guidance__facts dt { color: var(--text-2); font: var(--type-small); }
.readiness-guidance__value { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); margin: 0; min-width: 0; }
.readiness-guidance__code { color: var(--text-1); font: var(--type-small); font-family: var(--font-mono); overflow-wrap: anywhere; }
/* A destination waiting for launch (ADR-0063, amendment of 2026-10-18): its place and focus kept, muted, a lock at its
 * end, no hover fill, the not-allowed cursor; its page is one quiet panel. */
.sidebar__item--locked { color: var(--text-3); cursor: not-allowed; }
.sidebar__item--locked:hover { background-color: transparent; }
.sidebar__lock { display: inline-flex; margin-left: auto; color: var(--text-3); transition: opacity var(--dur-base) var(--ease-out); }
.sidebar[data-expanded="false"] .sidebar__lock { opacity: 0; }
@media (max-width: 831px) { .sidebar[data-expanded] .sidebar__lock { opacity: 1; } }
.launch-locked { display: flex; justify-content: center; padding-block: var(--space-10); }
.readiness-launched { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); margin-bottom: var(--space-6); }
.readiness-launched__text { display: flex; align-items: center; gap: var(--space-2); margin: 0; color: var(--text-2); }
.readiness-launched__icon { display: inline-flex; color: var(--status-on-track-fg); }
.readiness-launched > .status-line { flex-basis: 100%; }
.launch-card .readiness-launched { margin-bottom: 0; }
@container (max-width: 639px) {
  .readiness-guidance__facts { grid-template-columns: minmax(0, 1fr); }
  .readiness-guidance__facts dd + dt { margin-top: var(--space-2); }
}

/* The organisations' form's Zákazník / Partner toggle (client.views.operator-lists): the segmented control under the
 * field label, its track one step below the form's region as the fields beside it are. */
.inline-create__row > .kind-toggle { flex: none; max-width: none; }
.kind-toggle .segmented { align-self: flex-start; background-color: var(--holder-below); }
/* Responsive (operator 2026-10-18): stacked on a phone the toggle spans the form's width in two equal segments, as a
 * segmented control does on a phone; in the row it keeps its content's width, and when the acts no longer fit beside
 * the fields they wrap to their own line at the end edge rather than hanging at the start. */
@media (max-width: 767px) {
  .kind-toggle .segmented { align-self: stretch; }
  .kind-toggle .segmented__item { flex: 1 1 0; justify-content: center; }
}
@media (min-width: 768px) {
  .inline-create__row:has(> .kind-toggle) > .inline-create__actions { margin-left: auto; }
}
/* The partner select of a new customer stays mounted and folds away while Partner is chosen (operator 2026-10-18:
 * "animate the appearance/disappearance of the partner-assignment field"): in the stacked phone form its height, in
 * the row its width and the gap before it, with the neighbours reflowing on the same slow curve; it fades as it goes.
 * Folded it is inert, so nothing in it takes focus. Reduced motion zeroes the durations. */
.kind-partner {
  display: grid;
  grid-template-rows: 1fr;
  opacity: 1;
  transition: grid-template-rows var(--dur-slow) var(--ease-out), opacity var(--dur-base) var(--ease-out),
              flex-grow var(--dur-slow) var(--ease-out), flex-basis var(--dur-slow) var(--ease-out),
              margin var(--dur-slow) var(--ease-out);
}
.kind-partner > * { min-height: 0; min-width: 0; overflow: hidden; }
.kind-partner[data-folded="true"] { grid-template-rows: 0fr; opacity: 0; margin-top: calc(-1 * var(--space-3)); }
@media (min-width: 768px) {
  .inline-create__row > .kind-partner[data-folded="true"] { flex: 0 0 0px; margin-top: 0; margin-left: calc(-1 * var(--space-3)); }
}

/* == layout: the phishing console page while the simulations are not available (client.views.phishing) ==
 * One panel: a muted mark, the title with its state tag, a lead and three planned lines — nothing to act on. */
.coming-soon { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); max-width: 720px; }
.coming-soon__icon { display: inline-flex; color: var(--text-3); }
.coming-soon__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.coming-soon__head > h2 { margin: 0; }
.coming-soon__lead { max-width: 680px; margin: 0; color: var(--text-2); }
.coming-soon__list { display: flex; flex-direction: column; gap: var(--space-2); margin: 0; padding-left: var(--space-5); color: var(--text-2); }

/* == layout: the console Overview's charts (client.views.overview) ==
 * Every card the same width, so none is too narrow to read (operator, 2026-10-21): one to a row, in order, below
 * 1200 px; two equal columns from 1200 px, rows filled in order, a row's cards one height (the grid's stretch). */
.overview-charts { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--card-gap); margin-top: var(--card-gap); }
@media (min-width: 1200px) {
  .overview-charts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* == layout: the customer Overview (client.views.customer.overview) ==
 * A dashboard read top to bottom as one page stack: the headline figures (the tile band), the visual summaries, then the
 * operational lists. The three shares — participation, completion, test results — stand side by side where the page is
 * wide enough, one height, and the weekly trend under them across the whole row; one to a row below. The two lists —
 * the runs needing attention and the courses — share a row where both fit at a readable width, else they stack. */
.customer-overview-charts { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--card-gap); }
@media (min-width: 720px) {
  .customer-overview-charts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .customer-overview-charts > :nth-child(4) { grid-column: 1 / -1; }
}
.overview-lists { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 520px), 1fr)); gap: var(--card-gap); align-items: start; }
.overview-list { min-width: 0; }
.overview-list__note { margin: calc(-1 * var(--space-1)) 0 var(--space-3); color: var(--text-2); font: var(--type-small); }
/* The phone's link to the whole attention list, set apart from the items above by space alone. */
.overview-list__more { padding: var(--space-3) var(--space-4) var(--space-2); }

/* == layout: the page stack closes the file (`.page-stack`, with the page rhythm above) ==
 * Inside a page stack the stack's one gap is the only space between blocks: a block's own flow margin (a tile grid's,
 * a section's, a notice's) is cleared here, last, so it never adds to the gap whichever rule set it. */
.page-stack > * { margin-block: 0; }
