/* Novus console patterns (feature 007; constitution 1.11.0, Principles IV and VII).
   ONE source: admin-kits/shared/novus-admin.css. admin-kits/data/generate.mjs
   copies it into every Admin Kit flavor, and site/build.mjs serves it to the docs
   and prints each @pattern section on the matching component page.
   Reference: the novalending console (v2.1nflow.co), with its wrapping of short
   content corrected. Every value is a token; motion is 0.2s or less and removed
   under prefers-reduced-motion. Load after tokens.css. */

/* @pattern content-fit */
/* One short value, one line. Tables scroll inside .tablewrap instead of
   squeezing; free text opts back into wrapping; fixed slots truncate. */
.badge, .filterchip, .quickchip, .crumbs li, .paginator__label, .listfooter__range, .nowrap { white-space: nowrap; }
.truncate { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Positioned so the wrap is the containing block for its own absolutely positioned
   descendants. Without this, a .sr-only span inside a horizontally scrolled table
   resolves against the initial containing block, escapes this clip, and extends the
   document's scroll width: the page scrolls sideways on a phone while the table
   looks correctly contained. A popover inside a scrolling table must therefore be
   rendered outside the wrap, because it is now clipped by it. */
.tablewrap { position: relative; overflow-x: auto; overscroll-behavior-x: contain; }
.tablewrap table th, .tablewrap table td { white-space: nowrap; vertical-align: middle; }
.tablewrap table .cell--wrap { white-space: normal; min-width: 16rem; }
.table th.num, .table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.table th.cell--actions, .table td.cell--actions { text-align: right; width: 1%; }
.cell--actions .btn + .btn { margin-inline-start: var(--space-2); }
.cell-stack { display: flex; flex-direction: column; gap: calc(var(--space-1) / 2); }
.cell-stack__meta { font-size: var(--text-xs); line-height: var(--lh-xs); color: var(--text-secondary); }
/* Portal text uses the width of its row: the kit's reading measure is for
   prose, so console screens reset it. A measure is opted into explicitly
   (constitution 1.12.0, Principle IV). */
.adminmain p, .adminmain li, .authcard p, .settings p, .signedout p, .chartcard p { max-width: none; }
.measure { max-width: 68ch; }
/* @end */

/* @pattern icons */
.icon { width: 1.25rem; height: 1.25rem; flex: 0 0 auto; display: inline-block; vertical-align: middle; }
.icon--sm { width: 1rem; height: 1rem; }
.icon--lg { width: 1.5rem; height: 1.5rem; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* @end */

/* @pattern console-shell */
.adminwrap { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
.demobar { background: var(--bg-subtle); border-bottom: 1px solid var(--border); padding: var(--space-1) var(--gutter); font-size: var(--text-xs); color: var(--text-secondary); text-align: right; }
.appbar__inner { max-width: none; font-size: var(--text-sm); line-height: var(--lh-sm); }
.appheader { flex-wrap: nowrap; }
.appheader__left { min-width: 0; gap: var(--space-2); }
.appheader__right { min-width: 0; }
.appsuffix { font-size: var(--text-sm); white-space: nowrap; }
.appname { font-weight: var(--weight-bold); font-size: var(--text-lg); color: var(--text); }
/* A 44px target, anywhere. Named for the rule it satisfies rather than the
   menu toggle it was first written for. .toggle44 is the former name and
   keeps working, so nothing already shipped breaks. */
.target44, .toggle44 { min-height: 2.75rem; min-width: 2.75rem; }
.navtoggle { padding: 0; cursor: pointer; }
.navtoggle__input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.navtoggle__input:focus-visible ~ .appbar .navtoggle { box-shadow: var(--focus-ring); }

/* Endorsement: placed asset via tokens, dark swap under BOTH triggers */
.brandmark { display: block; height: var(--logo-height); width: 132px; background: var(--logo-master-colour) center/contain no-repeat; flex: 0 0 auto; }
[data-theme="dark"] .brandmark { background-image: var(--logo-master-white); }
@media (prefers-color-scheme: dark) { :root:not([data-theme]) .brandmark { background-image: var(--logo-master-white); } }
[data-theme="light"] .brandmark { background-image: var(--logo-master-colour); }

.adminbody { flex: 1; width: 100%; padding: var(--space-5) var(--gutter) var(--space-8); font-size: var(--text-sm); line-height: var(--lh-sm); }
.adminmain { min-width: 0; }
@media (min-width: 900px) {
  .adminbody { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: var(--space-6); align-items: start; }
  /* Collapsed at desktop width: a rail of icons, never nothing (feature 009). */
  .adminwrap:has(.navtoggle__input:checked) .adminbody { grid-template-columns: 3.5rem minmax(0, 1fr); }
  .adminwrap:has(.navtoggle__input:checked) .adminnav { align-items: center; }
  .adminwrap:has(.navtoggle__input:checked) .navlink { justify-content: center; gap: 0; width: 2.75rem; padding: 0; border-inline-start: 0; border-radius: var(--radius-md); }
  .adminwrap:has(.navtoggle__input:checked) .navlink > span,
  .adminwrap:has(.navtoggle__input:checked) .navgroup__label > span,
  .adminwrap:has(.navtoggle__input:checked) .navgroup__chevron { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .adminwrap:has(.navtoggle__input:checked) .navgroup { border-top-color: transparent; }
  .adminwrap:has(.navtoggle__input:checked) .navgroup:last-child { border-bottom-color: transparent; }
  .adminwrap:has(.navtoggle__input:checked) .navgroup__label { justify-content: center; padding: 0; min-height: 0; height: var(--space-4); cursor: default; }
  .adminwrap:has(.navtoggle__input:checked) .navgroup__label .icon { display: none; }
  .adminwrap:has(.navtoggle__input:checked) .navgroup > .navlink { padding-inline-start: 0; }
  /* A closed group still shows its destinations in the rail: the browser stops painting a
     closed details subtree, so the rail asks for it back. Rail mode only, so the phone
     drawer keeps ordinary group behaviour. */
  .adminwrap:has(.navtoggle__input:checked) .navgroup::details-content { content-visibility: visible; block-size: auto; }
  .navscrim { display: none; }
}
@media (max-width: 899.98px) {
  .navscrim { position: fixed; inset: 0; z-index: 60; background: var(--scrim); opacity: 0; visibility: hidden; transition: opacity 0.2s ease, visibility 0.2s ease; }
  .adminwrap:has(.navtoggle__input:checked) .navscrim { opacity: 1; visibility: visible; }
  body:has(.navtoggle__input:checked) { overflow: hidden; }
}
/* Two-mark rule below 520px: divider and suffix drop, endorsement steps down, never disappears */
@media (max-width: 519.98px) {
  .appsuffix, .appheader__sep { display: none; }
  .brandmark { height: 20px; width: 65px; }
  .appbar__inner, .appheader__right { gap: var(--space-2); }
}

/* Icon theme toggle (moon in light, sun in dark), mirrored under both triggers */
.themetoggle .ic-sun { display: none; }
[data-theme="dark"] .themetoggle .ic-moon { display: none; }
[data-theme="dark"] .themetoggle .ic-sun { display: inline-block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .themetoggle .ic-moon { display: none; }
  :root:not([data-theme]) .themetoggle .ic-sun { display: inline-block; }
}
[data-theme="light"] .themetoggle .ic-moon { display: inline-block; }
[data-theme="light"] .themetoggle .ic-sun { display: none; }
/* @end */

/* @pattern side-navigation */
.adminnav { display: flex; flex-direction: column; }
.adminnav__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); min-height: 3.5rem; padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4); margin-bottom: var(--space-2); border-bottom: 1px solid var(--border); }
@media (min-width: 900px) {
  .adminnav { position: sticky; top: var(--space-4); max-height: calc(100vh - var(--space-6)); overflow-y: auto; }
  .adminnav__head { display: none; }
}
@media (max-width: 899.98px) {
  .adminnav { position: fixed; inset-block: 0; inset-inline-start: 0; z-index: 70; width: min(20rem, 85vw); padding-bottom: var(--space-6); overflow-y: auto; background: var(--surface); border-inline-end: 1px solid var(--border); box-shadow: var(--shadow-3); transform: translateX(-100%); visibility: hidden; transition: transform 0.2s ease, visibility 0.2s ease; }
  .adminwrap:has(.navtoggle__input:checked) .adminnav { transform: none; visibility: visible; }
}
.navlink { display: flex; align-items: center; gap: var(--space-2); min-height: 2.25rem; padding: var(--space-2) var(--space-3); color: var(--text-secondary); text-decoration: none; white-space: nowrap; border-inline-start: 2px solid transparent; transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease; }
.navlink:hover { color: var(--text); background: var(--bg-subtle); text-decoration: none; }
.navlink[aria-current="page"], .navlink.active { color: var(--accent-text); background: var(--accent-subtle); border-inline-start-color: var(--accent); font-weight: var(--weight-bold); }
.navlink:focus-visible, .navgroup__label:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.navgroup { border-top: 1px solid var(--border); }
.navgroup:last-child { border-bottom: 1px solid var(--border); }
.navgroup__label { list-style: none; display: flex; align-items: center; gap: var(--space-2); min-height: 2.25rem; padding: var(--space-2) var(--space-3); cursor: pointer; font-size: var(--text-xs); font-weight: var(--weight-regular); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-secondary); white-space: nowrap; transition: color 0.15s ease, background-color 0.15s ease; }
.navgroup__label::-webkit-details-marker { display: none; }
.navgroup__label > span { flex: 1; }
.navgroup__label:hover { color: var(--text); background: var(--bg-subtle); }
.navgroup__chevron { transition: transform 0.15s ease; }
.navgroup[open] > .navgroup__label .navgroup__chevron { transform: rotate(180deg); }
.navgroup > .navlink { padding-inline-start: calc(var(--space-3) + 1rem + var(--space-2)); }
@media (pointer: coarse) { .navlink, .navgroup__label { min-height: 2.75rem; } }
/* Variant: flat. For a product whose destinations are peers with no grouping to
   nest (a monitoring surface), the nav is one flat list. Its collapse control is
   a chevron pinned to the sidebar's own edge, not an appbar hamburger: collapsing
   hides only labels, so the button belongs beside the thing it collapses. It
   drives the same hidden checkbox, so every rail rule above applies unchanged. */
.adminnav--flat { position: relative; padding-block-start: var(--space-6); }
.navtoggle--edge { position: absolute; inset-block-start: var(--space-3); inset-inline-start: 100%; z-index: 5; translate: -50% 0; display: grid; place-items: center; width: 1.5rem; height: 1.5rem; padding: 0; border-radius: var(--radius-pill); background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-2); color: var(--text-secondary); cursor: pointer; }
.navtoggle--edge:hover { color: var(--text); }
.navtoggle--edge .icon { width: 1rem; height: 1rem; }
.navtoggle--edge .ic-expand { display: none; }
.adminwrap:has(.navtoggle__input:checked) .navtoggle--edge .ic-collapse { display: none; }
.adminwrap:has(.navtoggle__input:checked) .navtoggle--edge .ic-expand { display: block; }
@media (min-width: 900px) {
  .adminwrap:has(.adminnav--flat) .navtoggle { display: none; }
}
@media (max-width: 899.98px) {
  .navtoggle--edge { display: none; }
}
/* @end */

/* @pattern top-navigation */
/* The second console shell (feature 012): primary navigation in a bar under the
   header, with menus that open on CLICK, never on hover. Built on native details
   so it works when scripting does not run, like every other dismissable surface
   here. Below the desktop breakpoint this bar steps aside and the drawer from the
   side-navigation shell takes over, so there is one phone navigation in the kit.
   The side-navigation shell remains the default; see the catalog for which to
   choose. */
.topnav { position: relative; z-index: 50; background: var(--surface); border-bottom: 1px solid var(--border); }
/* No scroll container here. A menu is absolutely positioned inside this strip,
   and an ancestor that scrolls clips it: overflow-x: auto forces overflow-y to
   auto as well, so the dropdown would be cut off at the bar's own height. The
   bar wraps instead, which keeps every section reachable AND visible. */
.topnav__inner { display: flex; flex-wrap: wrap; align-items: stretch; gap: var(--space-1); max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.topnav__link, .topnav__trigger { display: inline-flex; align-items: center; gap: var(--space-2); min-height: 2.75rem; padding: var(--space-2) var(--space-3); color: var(--text-secondary); font-size: var(--text-sm); font-weight: var(--weight-regular); white-space: nowrap; text-decoration: none; border-bottom: 2px solid transparent; cursor: pointer; transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease; }
.topnav__link:hover, .topnav__trigger:hover { color: var(--text); background: var(--bg-subtle); text-decoration: none; }
.topnav__link:focus-visible, .topnav__trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* The current section stays marked while its menu is closed. */
.topnav__link[aria-current="page"], .topnav__item.is-current > .topnav__trigger { color: var(--accent-text); border-bottom-color: var(--accent); font-weight: var(--weight-bold); }
.topnav__item { position: relative; display: flex; }
.topnav__trigger { list-style: none; }
.topnav__trigger::-webkit-details-marker { display: none; }
.topnav__chevron { transition: transform 0.15s ease; }
.topnav__item[open] > .topnav__trigger .topnav__chevron { transform: rotate(180deg); }
.topnav__menu { position: absolute; inset-inline-start: 0; top: 100%; z-index: 60; min-width: 14rem; max-height: min(24rem, calc(100vh - 8rem)); overflow-y: auto; padding: var(--space-2); display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--text-sm); line-height: var(--lh-sm); }
.topnav__menu .navlink { border-inline-start: 0; border-radius: var(--radius-md); }
/* A console opts into this shell with .adminwrap--topnav. Above the breakpoint the
   strip is the navigation and the side column steps aside; below it the strip hides
   and the drawer from the side-navigation shell takes over, unchanged. */
.adminwrap--topnav .adminbody { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) {
  .adminwrap--topnav .adminnav { display: none; }
  .adminwrap--topnav .navtoggle { display: none; }
}
@media (max-width: 899.98px) { .topnav { display: none; } }
/* @end */

/* @pattern page-header */
.pagehead { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-5); }
.pagehead__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3) var(--space-4); flex-wrap: wrap; }
.pagehead h1 { margin: 0; font-size: var(--text-xl); line-height: var(--lh-xl); }
.adminmain h2 { font-size: var(--text-lg); line-height: var(--lh-lg); }
.adminmain h3 { font-size: var(--text-md); line-height: var(--lh-md); }
.pagehead__actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.pagehead__desc { margin: 0; }
/* Back opens a detail screen, above the title: a ghost button with the arrow, pulled
   left by its own padding so the arrow lines up with the title's first letter. */
.pagehead__back { align-self: flex-start; min-height: 2.75rem; margin-inline-start: calc(var(--space-3) * -1); }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; padding: 0; font-size: var(--text-sm); }
.crumbs li { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--text-secondary); }
.crumbs li + li::before { content: "/"; color: var(--text-muted); }
.crumbs a { color: var(--text-secondary); text-decoration: none; }
.crumbs a:hover { color: var(--text); text-decoration: underline; }
.crumbs [aria-current="page"] { color: var(--text); font-weight: var(--weight-medium); }
/* @end */

/* @pattern user-menu */
.userdd { position: relative; min-width: 0; }
.userdd__trigger { list-style: none; gap: var(--space-2); min-height: 2.75rem; max-width: 14rem; }
.userdd__trigger::-webkit-details-marker { display: none; }
.userdd[open] > .userdd__trigger { background: var(--accent-subtle); }
.userdd__name { max-width: 10rem; }
.userdd__menu { position: absolute; inset-inline-end: 0; top: calc(100% + var(--space-2)); z-index: 60; min-width: 17rem; padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); box-shadow: var(--shadow-3); font-size: var(--text-sm); line-height: var(--lh-sm); }
.userdd__who { display: flex; flex-direction: column; gap: calc(var(--space-1) / 2); min-width: 0; padding-bottom: var(--space-2); border-bottom: 1px solid var(--border); }
.userdd__who > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.userdd__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.userdd__item { display: flex; align-items: center; gap: var(--space-2); min-height: 2.5rem; margin: 0 calc(var(--space-3) * -1); padding: var(--space-1) var(--space-3); color: var(--text); text-decoration: none; }
.userdd__item:hover { background: var(--bg-subtle); text-decoration: none; }
.userdd__foot { display: flex; justify-content: flex-end; padding-top: var(--space-2); border-top: 1px solid var(--border); }
@media (max-width: 519.98px) {
  .userdd__name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
}
/* @end */

/* @pattern sign-in */
/* Authentication screens sit on the kit's near-white ground like every other
   screen (feature 009, replacing the deep brand panel from 007). The ambient
   line work carries the interest. Flat colour: no gradients, no glow. */
.authpage { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; background: var(--bg-subtle); }
.authsplit { flex: 1; display: flex; flex-direction: column; }
.authbrand { position: relative; overflow: hidden; display: flex; align-items: center; padding: var(--space-6) var(--gutter); color: var(--text-secondary); }
/* Ambient authentication art: slow looping line work on the flat brand ground,
   the one decorative motion the kit allows (constitution 1.12.0, Principle II). */
.authhero__art { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.authhero__trace { fill: none; stroke: var(--blue-200); stroke-width: 1; opacity: 0.9; stroke-dasharray: 220 900; animation: authtrace 13s linear infinite; }
.authhero__trace:nth-of-type(2) { animation-delay: -4s; }
.authhero__trace:nth-of-type(3) { animation-delay: -8s; }
.authhero__mark { fill: none; stroke: var(--blue-200); stroke-width: 1.5; opacity: 0.75; animation: authmark 9s ease-in-out infinite; transform-origin: center; }
.authhero__mark:nth-of-type(5) { animation-delay: -4.5s; }
.authbrand__inner { position: relative; }
@keyframes authtrace { from { stroke-dashoffset: 1120; } to { stroke-dashoffset: 0; } }
@keyframes authmark { 0%, 100% { opacity: 0.45; } 50% { opacity: 0.85; } }
@media (prefers-reduced-motion: reduce) {
  .authhero__trace, .authhero__mark { animation: none; }
}
.authbrand__inner { width: 100%; max-width: 28rem; margin-inline: auto; display: flex; flex-direction: column; gap: var(--space-4); }
/* The lockup keeps its normal treatment: the panel is a light surface now. */
.authpage .authbrand .vlogo .vmark { width: 2.5rem; height: 2.5rem; }
.authpage .authbrand .wm { font-size: var(--text-2xl); }
.authbrand__tagline { margin: 0; font-size: var(--text-lg); line-height: var(--lh-lg); color: var(--text-secondary); }
.authbrand__modules { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; padding: 0; }
.authbrand__modules li { display: inline-flex; align-items: center; min-height: 2rem; padding: var(--space-1) var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-pill); background: var(--surface); color: var(--text-secondary); font-size: var(--text-sm); white-space: nowrap; }
.authmain { flex: 1; display: grid; place-items: center; padding: var(--space-2) var(--gutter) var(--space-7); }
@media (min-width: 900px) {
  .authsplit { flex-direction: row; }
  .authbrand { flex: 1 1 50%; padding: var(--space-8); }
  .authmain { flex: 1 1 50%; padding: var(--space-7) var(--gutter); }
}
.authcard { width: 100%; max-width: 28.5rem; padding: var(--space-6); border-radius: var(--radius-xl); box-shadow: var(--shadow-2); border: 1px solid var(--border); }
@media (min-width: 480px) { .authcard { padding: var(--space-6) var(--space-7); } }
.authcard__mark { display: block; width: 2.75rem; height: 2.75rem; margin: 0 0 var(--space-5); fill: none; stroke: var(--accent-text); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.authcard__title { margin: 0 0 var(--space-2); font-size: var(--text-2xl); line-height: var(--lh-2xl); text-align: start; }
.authcard__sub { margin: 0 0 var(--space-5); font-size: var(--text-sm); line-height: var(--lh-sm); }
.authcard .field > label { font-size: var(--text-xs); line-height: var(--lh-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
.field__req { margin-inline-start: var(--space-1); color: var(--danger-text); }
.authcard .input { min-height: 2.75rem; background: var(--bg-subtle); border-color: var(--border); }
.authcard .input:hover { background: var(--bg-muted); }
.authcard .input:focus-visible { background: var(--surface); }
.authcard .field--error .input { border-color: var(--danger); }
.authcard .field__error { margin: 0; }
.pwgroup { position: relative; display: block; }
.pwgroup > .input { padding-inline-end: 3rem; }
.pwtoggle { position: absolute; inset-inline-end: var(--space-1); top: 50%; transform: translateY(-50%); display: none; align-items: center; justify-content: center; width: 2.75rem; height: 2.75rem; padding: 0; border: 0; border-radius: var(--radius-md); background: transparent; color: var(--text-secondary); cursor: pointer; }
@media (scripting: enabled) { .pwtoggle { display: inline-flex; } }
.pwtoggle:hover { color: var(--text); background: var(--bg-muted); }
.pwtoggle:focus-visible { outline: none; box-shadow: var(--focus-ring); color: var(--text); }
.pwtoggle .pwtoggle__hide, .pwtoggle[aria-pressed="true"] .pwtoggle__show { display: none; }
.pwtoggle[aria-pressed="true"] .pwtoggle__hide { display: inline-block; }
.authcard__submit { width: 100%; min-height: 2.75rem; margin-top: var(--space-2); font-size: var(--text-base); }
.authalt { display: flex; align-items: center; gap: var(--space-3); margin: var(--space-4) 0 var(--space-3); color: var(--text-muted); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); }
.authalt::before, .authalt::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.authcard__sso { width: 100%; min-height: 2.75rem; }
/* Forgot password is a screen in this flow, not a disclosure on the card, so the
   link and the step's back link are the same affordance: centred, accent, underlined. */
.authcard__forgot { margin-top: var(--space-3); font-size: var(--text-sm); text-align: center; }
.authcard__forgot > summary, .authcard__back { display: inline-flex; align-items: center; justify-content: center; min-height: 2.75rem; color: var(--accent-text); text-decoration: underline; cursor: pointer; }
.authcard__back { width: 100%; }
.authcard__forgot > summary { list-style: none; }
.authcard__forgot > summary::-webkit-details-marker { display: none; }
.authcard__forgot:focus-visible, .authcard__forgot > summary:focus-visible, .authcard__back:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }
.authcard__forgot > p { margin: 0 auto; max-width: 22rem; }
/* The one auth state with no fields: a circled check, the headline, then quiet links.
   Centred because there is nothing to fill and nothing to align to. */
.authcard__done, .authcard__done > .authcard__title { text-align: center; }
.authcard__done > .authcard__check { display: grid; place-items: center; width: 3rem; height: 3rem; margin: 0 auto var(--space-4); border-radius: var(--radius-pill); background: var(--success-subtle); color: var(--success-text); }
.authcard__done > .authcard__check > .icon { width: 1.5rem; height: 1.5rem; }
/* Its two actions sit side by side as equal buttons, never stacked: the primary is the
   next step (back to sign in), the secondary the fallback (resend). */
.authcard__links { display: flex; gap: var(--space-3); margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--border); }
.authcard__links > .btn { flex: 1; min-height: 2.75rem; }
/* An SSO-only workspace drops the password form entirely, so the provider button
   takes the primary slot instead of sitting under an "or". */
.authcard__sso--primary { background: var(--accent); color: var(--text-on-accent); }
.authcard__sso--primary:hover { background: var(--accent-hover); border-color: transparent; }
.authcard__note { margin: var(--space-3) 0 0; font-size: var(--text-sm); text-align: center; color: var(--text-muted); }
.authcard__back { width: 100%; margin-top: var(--space-3); }
.authcard__foot, .signedout__foot { display: flex; align-items: center; justify-content: center; gap: var(--space-2); font-size: var(--text-sm); }
.authcard__foot { margin-top: var(--space-4); }
.authcard__foot > .muted, .signedout__foot > .muted { white-space: nowrap; }
.authcard__foot .brandmark, .signedout__foot .brandmark { width: 108px; }
/* @end */

/* @pattern signed-out */
.signedout { min-height: 100vh; min-height: 100dvh; display: grid; place-items: center; padding: var(--space-7) var(--gutter); }
.signedout__card { width: 100%; max-width: 28.5rem; padding: var(--space-6); text-align: center; border-radius: var(--radius-xl); box-shadow: var(--shadow-2); }
.signedout__brand { display: flex; align-items: center; justify-content: center; gap: var(--space-2); }
.signedout__workspace { display: flex; align-items: center; justify-content: center; gap: var(--space-2); margin: var(--space-3) 0 0; font-size: var(--text-sm); color: var(--text-secondary); }
.signedout__title { margin: var(--space-4) 0 0; font-size: var(--text-2xl); line-height: var(--lh-2xl); }
.signedout__lead { margin: var(--space-2) 0 0; }
.signedout__actions { margin-top: var(--space-5); }
.signedout__actions .btn { min-height: 2.75rem; padding-inline: var(--space-5); }
.signedout__note { margin: var(--space-4) 0 0; font-size: var(--text-sm); color: var(--text-muted); }
.signedout__foot { margin-top: var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--border); }
/* @end */

/* @pattern filter-bar */
.filterbar { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-4); }
.quickchips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.quickchip { position: relative; display: inline-flex; align-items: center; gap: var(--space-1); min-height: 2.25rem; padding: var(--space-1) var(--space-3); border: 1px solid var(--border-strong); border-radius: var(--radius-pill); background: var(--surface); color: var(--text-secondary); font-size: var(--text-sm); font-weight: var(--weight-medium); cursor: pointer; transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease; }
.quickchip input { position: absolute; opacity: 0; pointer-events: none; }
.quickchip:hover { color: var(--text); border-color: var(--accent); }
.quickchip:has(input:checked) { color: var(--text-on-accent); background: var(--accent); border-color: var(--accent); }
.quickchip:has(input:focus-visible) { box-shadow: var(--focus-ring); }
.quickchip__count { font-weight: var(--weight-regular); font-variant-numeric: tabular-nums; }
.quickchip__count::before { content: "("; }
.quickchip__count::after { content: ")"; }
.filterbar__top { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.filterbar__search { position: relative; flex: 1 1 18rem; min-width: 0; display: flex; align-items: center; }
.filterbar__search > .icon { position: absolute; inset-inline-start: var(--space-3); color: var(--text-muted); pointer-events: none; }
.filterbar__search > .input { min-height: 2.75rem; padding-inline-start: calc(var(--space-3) + 1rem + var(--space-2)); }
.filtermenu { position: relative; flex: 0 0 auto; }
.filtermenu__trigger { list-style: none; display: inline-flex; align-items: center; gap: var(--space-2); min-height: 2.75rem; padding: var(--space-1) var(--space-3); border: 1px solid var(--border-strong); border-radius: var(--radius-md); background: var(--surface); color: var(--text-secondary); font-size: var(--text-sm); font-weight: var(--weight-medium); white-space: nowrap; cursor: pointer; transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease; }
.filtermenu__trigger::-webkit-details-marker { display: none; }
.filtermenu__trigger:hover { color: var(--text); background: var(--bg-subtle); }
.filtermenu__trigger:focus-visible { outline: none; border-color: var(--accent); box-shadow: var(--focus-ring); }
.filtermenu[open] > .filtermenu__trigger, .filtermenu__trigger--on { color: var(--accent-text); border-color: var(--accent); background: var(--accent-subtle); }
.filtermenu__count, .filtermenu__tabcount { min-width: 1.25rem; padding: 0 var(--space-1); border-radius: var(--radius-pill); background: var(--accent); color: var(--text-on-accent); font-size: var(--text-xs); line-height: var(--lh-xs); text-align: center; font-variant-numeric: tabular-nums; }
.filtermenu__count[hidden], .filtermenu__tabcount[hidden] { display: none; }
.filtermenu__sheet { position: absolute; inset-inline-end: 0; top: calc(100% + var(--space-1)); z-index: 40; display: grid; grid-template-columns: minmax(9rem, max-content) minmax(14rem, 1fr); width: min(34rem, calc(100vw - 2 * var(--gutter))); overflow: hidden; background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: var(--shadow-2); font-size: var(--text-sm); line-height: var(--lh-sm); }
.filtermenu__tabs { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-2); background: var(--bg-subtle); border-inline-end: 1px solid var(--border); }
.filtermenu__tab { position: relative; display: flex; align-items: center; gap: var(--space-2); min-height: 2.5rem; padding: var(--space-1) var(--space-2); border: 1px solid transparent; border-radius: var(--radius-sm); color: var(--text); white-space: nowrap; cursor: pointer; }
.filtermenu__tab input { position: absolute; opacity: 0; pointer-events: none; }
.filtermenu__tab > .truncate { flex: 1; }
.filtermenu__chev { color: var(--text-muted); }
.filtermenu__tab:hover { background: var(--surface); }
.filtermenu__tab:has(input:checked) { color: var(--accent-text); background: var(--surface); border-color: var(--accent); }
.filtermenu__tab:has(input:focus-visible) { box-shadow: var(--focus-ring); }
.filtermenu__panels { min-width: 0; }
.filtermenu__panel { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; max-height: min(20rem, 60vh); margin: 0; padding: var(--space-3); overflow-y: auto; border: 0; }
.filtermenu__head { padding: 0; margin-bottom: var(--space-1); font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--text-secondary); }
/* the N-th category tab shows the N-th panel; without :has every panel stays listed */
@supports selector(:has(*)) {
  .filtermenu__sheet:has(.filtermenu__tab input:checked) .filtermenu__panel { display: none; }
  .filtermenu__sheet:has(.filtermenu__tab:nth-child(1) input:checked) .filtermenu__panel:nth-child(1),
  .filtermenu__sheet:has(.filtermenu__tab:nth-child(2) input:checked) .filtermenu__panel:nth-child(2),
  .filtermenu__sheet:has(.filtermenu__tab:nth-child(3) input:checked) .filtermenu__panel:nth-child(3),
  .filtermenu__sheet:has(.filtermenu__tab:nth-child(4) input:checked) .filtermenu__panel:nth-child(4),
  .filtermenu__sheet:has(.filtermenu__tab:nth-child(5) input:checked) .filtermenu__panel:nth-child(5),
  .filtermenu__sheet:has(.filtermenu__tab:nth-child(6) input:checked) .filtermenu__panel:nth-child(6) { display: flex; }
}
.filteropt { display: flex; align-items: center; gap: var(--space-2); min-height: 2.25rem; padding: 0 var(--space-2); border-radius: var(--radius-sm); color: var(--text); cursor: pointer; }
.filteropt:hover { background: var(--bg-subtle); }
.filteropt input { width: 1rem; height: 1rem; flex: 0 0 auto; margin: 0; accent-color: var(--accent); }
.filteropt > .truncate { flex: 1; }
.filterdate { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); min-height: 2.75rem; font-size: var(--text-sm); }
.filterdate .input { width: 10rem; min-height: 2.75rem; }
.filterchips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.filterchips[hidden] { display: none; }
.filterchip { display: inline-flex; align-items: center; gap: var(--space-1); max-width: 100%; min-height: 2rem; padding-inline-start: var(--space-3); border: 1px solid var(--accent); border-radius: var(--radius-pill); background: var(--accent-subtle); color: var(--text); font-size: var(--text-sm); }
.filterchip__group { font-size: var(--text-xs); color: var(--text-secondary); }
.filterchip__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.filterchip__remove { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; padding: 0; border: 0; border-radius: var(--radius-pill); background: transparent; color: var(--accent-text); cursor: pointer; }
.filterchip__remove::after { content: ""; position: absolute; inset: calc(var(--space-2) * -0.75); }
.filterchip__remove:hover { background: var(--surface); }
.filterchip__remove:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.linkbtn { min-height: 2.25rem; padding: var(--space-1) var(--space-2); border: 0; border-radius: var(--radius-sm); background: transparent; font: inherit; font-size: var(--text-sm); color: var(--accent-text); text-decoration: underline; white-space: nowrap; cursor: pointer; }
.linkbtn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* A dropdown in a toolbar is a trigger, not a text field: same height, radius and
   inset padding as the Filters button above, so a row of them reads as one set of
   controls. The row's inline padding keeps the first and last control off the edge
   it scrolls against; a control flush to that edge reads as clipped, not as last. */
.filterrow { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-4); padding-inline: var(--space-1); }
.filterrow--nowrap { flex-wrap: nowrap; overflow-x: auto; padding-bottom: var(--space-1); }
.filterrow--nowrap > * { flex: 0 0 auto; }
.filterrow--nowrap > input[type="search"] { flex: 1 1 14rem; min-width: 11rem; }
.filterrow--nowrap > .input { width: auto; }
.filterrow--nowrap > input[type="date"] { width: 9.5rem; }
.filterrow > .btn { min-height: 2.75rem; }
@media (pointer: coarse) { .quickchip, .filteropt, .filtermenu__tab, .linkbtn { min-height: 2.75rem; } }
@media (pointer: coarse) { .userdd__item { min-height: 2.75rem; } }
@media (max-width: 40rem) {
  .filterbar__top { position: relative; }
  .filtermenu { position: static; }
  .filtermenu__sheet { inset-inline: 0; width: auto; grid-template-columns: minmax(0, 1fr); }
  .filtermenu__tabs { flex-direction: row; flex-wrap: wrap; border-inline-end: 0; border-bottom: 1px solid var(--border); }
  .filtermenu__chev { display: none; }
}
/* @end */

/* @pattern list-footer */
.listfooter { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-3); font-size: var(--text-sm); line-height: var(--lh-sm); }
.listfooter__range { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.listfooter__controls { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.listfooter .selectwrap { display: inline-block; }
.paginator { display: flex; align-items: center; gap: var(--space-2); color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.paginator button { display: inline-flex; align-items: center; justify-content: center; min-width: 2.75rem; min-height: 2.75rem; padding: 0; font: inherit; color: var(--accent-text); background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius-md); cursor: pointer; transition: background-color 0.15s ease, border-color 0.15s ease; }
.paginator button:hover:not(:disabled) { background: var(--accent-subtle); border-color: var(--accent); }
.paginator button:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.paginator button:disabled { opacity: var(--opacity-disabled); cursor: default; }
.paginator__label { padding-inline: var(--space-1); color: var(--text); }
/* @end */

/* @pattern data-grid */
/* Sortable headers for the static flavors, and QuickGrid themed with kit tokens */
.gridsort { font: inherit; font-weight: var(--weight-medium); color: var(--text-secondary); background: none; border: 0; padding: 0; cursor: pointer; min-height: 2.75rem; white-space: nowrap; }
.gridsort:hover { color: var(--text); }
.gridsort[data-dir="asc"]::after { content: " \2191"; color: var(--accent-text); }
.gridsort[data-dir="desc"]::after { content: " \2193"; color: var(--accent-text); }
.quickgrid { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.quickgrid th, .quickgrid td { text-align: left; padding: calc(var(--space-2) + var(--space-1) / 2) var(--space-3); border-bottom: 1px solid var(--border); }
.quickgrid .col-header-content { justify-content: flex-start; }
.quickgrid th.col-justify-end .col-header-content { justify-content: flex-end; }
.quickgrid thead th { background: var(--bg-subtle); color: var(--text-secondary); font-weight: var(--weight-medium); }
.quickgrid tbody tr:hover { background: var(--bg-subtle); }
.quickgrid .col-header-content button, .quickgrid button.col-title { font: inherit; font-weight: var(--weight-medium); color: var(--text-secondary); background: none; border: 0; padding: 0; cursor: pointer; min-height: 2.75rem; display: inline-flex; align-items: center; gap: var(--space-1); }
.quickgrid .col-header-content button:hover, .quickgrid button.col-title:hover { color: var(--text); }
.quickgrid td[align="right"], .quickgrid .grid-cell-align-right { text-align: right; font-variant-numeric: tabular-nums; }
/* @end */

/* @pattern console-screens */
/* Dashboard, empty state, dialogs, settings tabs: the console screens' own compositions */
.statpanel { margin-bottom: var(--space-6); }
.adminmain h1:focus { outline: none; }
.stat__value { white-space: nowrap; }
.signalgrid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); margin-bottom: var(--space-6); }
.signal { border-left: 3px solid var(--border); }
.signal--danger { border-left-color: var(--danger); }
.signal--danger h3 { color: var(--danger-text); }
.signal--warning { border-left-color: var(--warning); }
.signal h3 { font-size: var(--text-md); line-height: var(--lh-md); margin-bottom: var(--space-1); }
.signal .muted { margin: 0; }
.signal .eyebrow { margin: 0 0 var(--space-2); font-size: var(--text-xs); line-height: var(--lh-xs); font-weight: var(--weight-medium); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-muted); }
.card--flush { padding: 0; overflow: hidden; }
.cardhead { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-4) var(--space-4) var(--space-3); }
.cardhead h2 { margin: 0; font-size: var(--text-lg); line-height: var(--lh-lg); }
.settingsec h2 { margin: 0; font-size: var(--text-lg); line-height: var(--lh-lg); }
.emptystate { padding: var(--space-6); text-align: center; color: var(--text-secondary); }
.emptystate[hidden] { display: none; }
.chk { display: flex; gap: var(--space-2); align-items: center; min-height: 2.75rem; cursor: pointer; }
.selectwrap { position: relative; display: block; }
.selectwrap .select { appearance: none; padding-right: calc(var(--space-5) + var(--space-4)); }
.selectwrap::after { content: ""; position: absolute; right: var(--space-5); top: 50%; width: 0.5rem; height: 0.5rem; border-right: 2px solid var(--text-secondary); border-bottom: 2px solid var(--text-secondary); transform: translateY(-70%) rotate(45deg); pointer-events: none; }
/* A dropdown that sits in a row of controls is a trigger, not a text field: the
   Filters button's height, radius and inset padding, so a row of them reads as one
   set instead of a field parked among buttons. A dropdown inside a .field keeps the
   field treatment: it has a label above it and fills the column. */
.filterrow .select, .listfooter .select { width: auto; min-height: 2.75rem; padding-block: 0; padding-inline-start: var(--space-3); border-radius: var(--radius-md); }
details > summary::marker { font-size: var(--text-lg); }

.tablist { display: flex; flex-wrap: wrap; gap: var(--space-1); border-bottom: 1px solid var(--border); margin-bottom: var(--space-4); }
.tablist input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; }
.tablist label { position: relative; cursor: pointer; padding: var(--space-2) var(--space-3); min-height: 2.75rem; display: inline-flex; align-items: center; color: var(--text-secondary); font-size: var(--text-sm); font-weight: var(--weight-medium); white-space: nowrap; transition: color 0.15s ease, background-color 0.15s ease; }
.tablist label::after { content: ""; position: absolute; left: var(--space-3); right: var(--space-3); bottom: -1px; height: 2px; background: var(--accent); transform: scaleX(0); transition: transform 0.18s ease; }
.tablist label:hover { color: var(--text); background: var(--bg-subtle); border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.tablist input:checked + label { color: var(--accent-text); }
.tablist input:checked + label::after { transform: scaleX(1); }
.tablist input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius-sm); }
.tabpanel { animation: tabfade 0.18s ease; }
/* JS-off and no-:has fallback: all panels stay visible stacked */
.tabs:has(input:checked) .tabpanel { display: none; }
.tabs:has(#tab-profile:checked) #panel-profile,
.tabs:has(#tab-appearance:checked) #panel-appearance,
.tabs:has(#tab-notifications:checked) #panel-notifications,
.tabs:has(#tab-api:checked) #panel-api { display: block; }
@keyframes tabfade { from { opacity: 0; transform: translateY(4px); } }
/* @end */

@media (prefers-reduced-motion: reduce) {
  .navlink, .navgroup__label, .navgroup__chevron, .adminnav, .navscrim, .quickchip, .filtermenu__trigger, .paginator button, .tablist label, .tablist label::after { transition: none; }
  .tabpanel { animation: none; }
}

/* @pattern settings-layout */
/* Configuration screens: a section menu beside grouped sections of labelled
   rows. Anchors, so it works with JavaScript off (constitution 1.12.0, VII). */
.settings { display: flex; flex-direction: column; gap: var(--space-4); }
.settings__menu { display: flex; gap: var(--space-1); overflow-x: auto; padding-bottom: var(--space-1); border-bottom: 1px solid var(--border); }
.settings__link { display: inline-flex; align-items: center; gap: var(--space-2); min-height: 2.25rem; padding: var(--space-1) var(--space-3); border-radius: var(--radius-sm); color: var(--text-secondary); text-decoration: none; white-space: nowrap; transition: color 0.15s ease, background-color 0.15s ease; }
.settings__link:hover { color: var(--text); background: var(--bg-subtle); text-decoration: none; }
.settingsec { scroll-margin-top: var(--space-5); }
.settingsec:target .settingsec__head { border-inline-start-color: var(--accent); }
.settingsec__head { padding-inline-start: var(--space-3); border-inline-start: 2px solid transparent; margin-bottom: var(--space-3); }
.settingsec__head p { margin: var(--space-1) 0 0; }
.setting { display: grid; gap: var(--space-2) var(--space-5); grid-template-columns: minmax(0, 1fr); padding: var(--space-4) 0; border-top: 1px solid var(--border); }
.setting:first-of-type { border-top: 0; }
.setting__text { min-width: 0; }
.setting__label { display: block; font-weight: var(--weight-medium); }
.setting__desc { display: block; margin-top: calc(var(--space-1) / 2); color: var(--text-secondary); }
.setting__control { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.setting__control .input, .setting__control .select, .setting__control md-filled-text-field, .setting__control md-outlined-text-field { width: 100%; }
.setting .field { margin: 0; }
@media (min-width: 900px) {
  .settings { display: grid; grid-template-columns: 14rem minmax(0, 1fr); gap: var(--space-6); align-items: start; }
  .settings__menu { position: sticky; top: var(--space-4); flex-direction: column; overflow: visible; padding: 0; border-bottom: 0; border-inline-end: 1px solid var(--border); }
  .settings__link { border-inline-start: 2px solid transparent; border-radius: 0; }
  .settings__link:hover { border-inline-start-color: var(--border-strong); }
  .setting { grid-template-columns: minmax(0, 1fr) minmax(12rem, 22rem); align-items: center; }
}
@media (pointer: coarse) { .settings__link { min-height: 2.75rem; } }
/* @end */

/* @pattern charts */
/* D3 charts under the locked Novus rules: the frame owns sizing and the
   tooltip, the chart owns nothing but tokens (constitution 1.12.0, VII). */
.chartframe { position: relative; width: 100%; min-width: 0; height: 22rem; }
.chartframe--short { height: 14rem; }
.chart { display: block; overflow: visible; }
.chart text { font-size: var(--text-xs); font-family: var(--font-sans); }
.chart__centre { font-size: var(--text-lg); font-weight: var(--weight-bold); }
.chart [tabindex]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.charttip { position: absolute; z-index: 20; min-width: 9rem; padding: var(--space-2) var(--space-3); border-radius: var(--radius-md); background: var(--neutral-900); color: var(--neutral-0); font-size: var(--text-xs); line-height: var(--lh-xs); pointer-events: none; box-shadow: var(--shadow-2); display: flex; flex-direction: column; gap: calc(var(--space-1) / 2); }
.charttip[hidden] { display: none; }
.charttip b { font-size: var(--text-sm); }
.charttip span { display: flex; align-items: center; gap: var(--space-2); white-space: nowrap; }
.charttip i { width: 0.5rem; height: 0.5rem; border-radius: var(--radius-pill); flex: 0 0 auto; }
.charttip__total { border-top: 1px solid var(--neutral-700); margin-top: calc(var(--space-1) / 2); padding-top: calc(var(--space-1) / 2); }
.statgrid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); align-items: start; margin-bottom: var(--space-6); }
.chartcard { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.chartcard__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-1) var(--space-3); }
.chartcard__head h2, .chartcard__head h3 { margin: 0; }
.tabledetails > summary { display: inline-flex; align-items: center; min-height: 2.75rem; color: var(--accent-text); cursor: pointer; font-size: var(--text-sm); }
.tabledetails > summary::-webkit-details-marker { display: none; }
.tabledetails[open] > summary { margin-bottom: var(--space-2); }
/* @end */

/* @pattern app-switcher */
/* The Novus app switcher (feature 014), drawn by <novus-app-switcher> from
   js/novus-app-switcher.js. It is the first control in a console header in either
   shell: nothing sits to the left of it, and on a phone the drawer toggle follows
   it. A 40px nine-dot button, pressed through a 44px hit area, opens a panel
   anchored under it at the left edge: 640px wide on a desktop, a full-width sheet
   under the header below 600px. Search comes first, then the app tiles, five to a
   row on a desktop, four on a tablet and three on a phone, with "All apps" last.
   Surface, border, radius and elevation follow the theme, while each product mark
   keeps its own colour in both themes. */
novus-app-switcher { position: relative; display: inline-flex; flex: 0 0 auto; }
novus-app-switcher[hidden] { display: none; }
.nv-apps__button { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; padding: 0; border: 0; border-radius: var(--radius-md); background: transparent; color: inherit; cursor: pointer; transition: background-color var(--dur-fast) var(--ease-out); }
.nv-apps__button::after { content: ""; position: absolute; inset: -0.125rem; }
.nv-apps__button:hover { background: color-mix(in srgb, currentColor 8%, transparent); }
.nv-apps__button[aria-expanded="true"] { background: color-mix(in srgb, currentColor 14%, transparent); }
.nv-apps__button:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.nv-apps__panel { position: absolute; inset-inline-start: 0; top: calc(100% + var(--space-2)); z-index: 70; box-sizing: border-box; width: min(40rem, calc(100vw - 2 * var(--gutter))); max-height: calc(100vh - 6rem); overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4); background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-3); font-size: var(--text-sm); line-height: var(--lh-sm); text-align: start; animation: nvappsin var(--dur-fast) var(--ease-out); }
.nv-apps__panel[hidden] { display: none; }
.nv-apps__panel:focus { outline: none; }
.nv-apps__search { position: relative; display: flex; align-items: center; }
.nv-apps__lens { position: absolute; inset-inline-start: var(--space-3); color: var(--text-muted); pointer-events: none; }
.nv-apps__input { min-height: 2.75rem; padding-inline-start: calc(var(--space-3) + 1rem + var(--space-2)); }
.nv-apps__status { margin: 0; color: var(--text-secondary); }
.nv-apps__grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--space-1); }
.nv-apps__grid > li { min-width: 0; display: flex; }
.nv-apps__tile { box-sizing: border-box; display: flex; flex-direction: column; align-items: center; gap: var(--space-2); width: 100%; min-width: 0; padding: var(--space-3) var(--space-1); border-radius: var(--radius-md); color: var(--text); text-decoration: none; transition: background-color var(--dur-fast) var(--ease-out); }
a.nv-apps__tile:hover { background: var(--bg-subtle); color: var(--text); text-decoration: none; }
.nv-apps__tile:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.nv-apps__tile--current { background: var(--accent-subtle); cursor: default; }
/* A product mark: a square of the product's colour with its white line glyph. */
.nv-apps__mark { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: var(--space-7); height: var(--space-7); border-radius: var(--radius-lg); color: var(--neutral-0); font-size: var(--text-lg); font-weight: var(--weight-medium); line-height: 1; }
.nv-apps__mark--all { background: transparent; color: var(--text-secondary); border: 1px solid var(--border-strong); }
.nv-apps__name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 899.98px) { .nv-apps__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 599.98px) {
  .nv-apps__panel { position: fixed; inset-inline: 0; top: var(--nv-apps-top, 3.5rem); width: auto; max-height: calc(100dvh - var(--nv-apps-top, 3.5rem)); padding: var(--space-3) var(--gutter) var(--space-4); border-inline: 0; border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
  .nv-apps__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@keyframes nvappsin { from { opacity: 0; transform: translateY(-4px); } }
@media (prefers-reduced-motion: reduce) {
  .nv-apps__panel { animation: none; }
  .nv-apps__button, .nv-apps__tile { transition: none; }
}
/* @end */

/* @pattern target-size */
/* Gate 19: at the 375px baseline every control a finger can press clears 44px.
   This sits last on purpose: the pattern sections above set their own compact
   heights, and an equal-specificity rule only wins by order. Desktop density
   (the console decision from feature 003) is untouched, because this is a
   phone-width floor; the pointer rule in the side navigation covers touch
   laptops, which a width query cannot see. tokens.css defines most of these
   controls and is frozen, so the floor lives here. */
@media (max-width: 899.98px) {
  .navlink,
  .navgroup__label,
  .btn,
  .linkbtn,
  .modal-close,
  .input,
  .select,
  .textarea,
  .chip,
  .quickchip,
  .quickchip > label,
  .filteropt,
  .filtermenu__tab,
  .settings__link,
  summary,
  input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),
  select,
  textarea { min-height: 2.75rem; }
  .btn, .linkbtn { padding-block: var(--space-2); }
  .modal-close { min-width: 2.75rem; }
}
/* @end */
