/* =====================================================================
   TUMRIX STUDIO - THE CONSOLE

   The approved direction, built rather than described. Four ideas hold
   the whole sheet together:

     ONE RHYTHM.  Every gap, pad and inset is one of --cs-1 .. --cs-8, an
     8px grid. Nothing in this file is eyeballed, so nothing drifts.

     ONE BUTTON FAMILY.  Primary, secondary, ghost, destructive and icon,
     in three sizes, each with rest / hover / press / focus / disabled /
     busy. A destructive action is tinted and outlined rather than filled:
     it must read as serious without shouting across the room.

     FOUR SPEEDS.  --t-response is contact, --t-transition is a thing
     changing place, --t-arrival is a view appearing, --t-ambient is the
     aura. Motion here always says what changed -- where a thing came
     from, what it became, that it worked -- and the whole system stops
     when the device asks for reduced motion.

     EVERY COLOUR FROM A TOKEN.  Not one literal below. A literal is how
     two surfaces drift apart, and how a dark appearance ends up wearing
     one corner of a light one.

   Loaded last, so it refines what the shared sheets establish rather
   than restating them.
   ===================================================================== */

/* =====================================================================
   1. THE FRAME
   ===================================================================== */

/* The grid, and the promise that nothing moves the page sideways.
   `overflow-x: clip` rather than `hidden`: `hidden` would make this a
   scroll container and break the sticky header and rail inside it.
   The middle track is `minmax(0, 1fr)` because a 36-character identifier
   in a grid child with an `auto` minimum widens the whole console. */
.console {
  display: grid;
  grid-template-columns: var(--console-nav) minmax(0, 1fr) var(--console-context);
  grid-template-areas:
    "head head head"
    "nav  work ctx";
  /* The header takes the height it needs; everything else takes the rest.
     Two `auto` rows would share the leftover height of a tall viewport
     between them, and the console would open with a band of nothing under
     its own header. */
  grid-template-rows: auto minmax(0, 1fr);
  min-height: 100dvh;
  max-width: 100%;
  background: var(--console-bg);
  color: var(--fg);
  overflow-x: clip;
  position: relative;
}

/* The aura: two slow gradients, well behind everything, drifting over
   half a minute. It is the only decorative motion in the console, and it
   is the first thing reduced motion switches off. */
.console::before {
  content: "";
  position: fixed;
  inset: -20% -10% auto;
  height: 70vh;
  z-index: 0;
  pointer-events: none;
  filter: blur(70px);
  background:
    radial-gradient(38% 50% at 18% 30%, var(--console-aura-1) 0%, transparent 70%),
    radial-gradient(34% 46% at 74% 16%, var(--console-aura-2) 0%, transparent 72%);
  animation: console-drift var(--t-ambient) var(--ease) infinite alternate;
}
@keyframes console-drift {
  from { transform: translate3d(-3%, 0, 0) scale(1); }
  to   { transform: translate3d(4%, 3%, 0) scale(1.12); }
}

/* =====================================================================
   2. THE COMMAND HEADER
   ===================================================================== */

.console-head {
  grid-area: head;
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: var(--cs-4);
  min-height: var(--console-head-h);
  padding: var(--cs-2) var(--console-pad);
  background: var(--console-head-bg);
  border-bottom: var(--hairline) solid var(--line);
  backdrop-filter: blur(var(--blur-dock)) saturate(var(--glass-sat));
  -webkit-backdrop-filter: blur(var(--blur-dock)) saturate(var(--glass-sat));
}

.brand { display: flex; align-items: center; gap: var(--cs-3); min-width: 0; }
.brand-mark {
  position: relative;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  border-radius: var(--r-md);
  overflow: hidden;
  color: var(--fg-on-accent);
  background: linear-gradient(145deg, var(--accent), var(--violet));
  box-shadow: var(--console-glow);
}
/* A single pass of light across the mark, every six seconds. It is the
   console saying it is live, and it costs one pseudo-element. */
.brand-mark::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 35%, var(--skeleton-shine) 50%, transparent 65%);
  transform: translateX(-120%);
  animation: brand-sheen 6s var(--ease) infinite;
}
@keyframes brand-sheen {
  0%, 68% { transform: translateX(-120%); }
  86%, 100% { transform: translateX(120%); }
}
.brand-name {
  margin: 0;
  font-size: var(--fs-heading);
  font-weight: var(--fw-heavy);
  letter-spacing: var(--ls-tight);
  line-height: var(--lh-tight);
  color: var(--fg);
}
.brand-sub {
  margin: 0;
  font-size: var(--fs-micro);
  color: var(--fg-muted);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}

/* The command field searches what this browser already holds. It never
   fetches, so it can never be slow, and it says so by sitting quiet. */
.cmd {
  display: flex;
  align-items: center;
  gap: var(--cs-2);
  flex: 1 1 22rem;
  min-width: 0;
  max-width: 34rem;
  height: 2.375rem;
  padding: 0 var(--cs-3);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--fg-muted);
  transition: border-color var(--t-response) var(--ease),
              box-shadow var(--t-transition) var(--ease);
}
.cmd:hover { border-color: var(--line-strong); box-shadow: var(--shadow-sm); }
.cmd:focus-within { border-color: var(--accent); box-shadow: var(--console-glow); }
.cmd input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--fg);
  font: inherit;
  font-size: var(--fs-sub);
  outline: none;
}
.cmd input::-webkit-search-cancel-button { filter: grayscale(1); }
.cmd-hint {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  line-height: 1;
  padding: 0.2rem 0.4rem;
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-xs);
  background: var(--surface-muted);
  color: var(--fg-muted);
}

.head-actions { margin-left: auto; display: flex; align-items: center; gap: var(--cs-2); }

.nav-toggle {
  display: none;
  place-items: center;
  width: 2.375rem;
  height: 2.375rem;
  flex: none;
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--fg-2);
  cursor: pointer;
  transition: color var(--t-response) var(--ease), border-color var(--t-response) var(--ease);
}
.nav-toggle:hover { color: var(--accent); border-color: var(--accent); }

/* The administrator. Violet, because violet is identity in this console
   and identity is never an action. */
.identity-wrap { position: relative; }
.identity-chip {
  display: flex;
  align-items: center;
  gap: var(--cs-2);
  padding: var(--cs-1) var(--cs-3) var(--cs-1) var(--cs-1);
  border: var(--hairline) solid var(--violet-line);
  border-radius: var(--r-pill);
  background: var(--violet-wash);
  color: var(--fg);
  font-size: var(--fs-sub);
  cursor: pointer;
  transition: background var(--t-response) var(--ease), transform var(--t-response) var(--ease);
}
.identity-chip:hover { background: var(--violet-wash); transform: translateY(-1px); }
.identity-chip:active { transform: translateY(0) scale(0.98); }
.identity-mark {
  display: grid;
  place-items: center;
  width: 1.625rem;
  height: 1.625rem;
  flex: none;
  border-radius: var(--r-pill);
  background: linear-gradient(145deg, var(--violet), var(--accent));
  color: var(--fg-on-accent);
}
.identity-menu {
  position: absolute;
  right: 0;
  top: calc(100% + var(--cs-2));
  z-index: 70;
  width: min(23rem, 90vw);
  padding: var(--cs-4);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-dock);
  animation: console-pop var(--t-transition) var(--ease-spring) both;
}
@keyframes console-pop {
  from { opacity: 0; transform: translateY(-6px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
.ident-field {
  display: flex;
  align-items: center;
  gap: var(--cs-2);
  padding: var(--cs-2) var(--cs-3);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-muted);
  min-width: 0;
}
.ident-field code {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  overflow-wrap: anywhere;
}

/* =====================================================================
   3. THE NAVIGATION RAIL
   ===================================================================== */

.console-nav {
  grid-area: nav;
  z-index: 1;
  position: sticky;
  top: var(--console-head-h);
  max-height: calc(100dvh - var(--console-head-h));
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--cs-5);
  padding: var(--cs-4) var(--cs-3) var(--cs-6);
  border-right: var(--hairline) solid var(--line);
  background: var(--console-nav-bg);
}

/* The marker is one element that moves between the sections, so the
   change of place is the animation. Sections themselves only change
   colour: two things sliding at once reads as a glitch. */
.nav-group { position: relative; display: flex; flex-direction: column; gap: var(--cs-1); }
.nav-marker {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 0;
  border-radius: var(--r-md);
  background: var(--surface-muted);
  box-shadow: inset 0 0 0 var(--hairline) var(--line);
  opacity: 0;
  z-index: 0;
  transition: transform var(--t-transition) var(--ease-emphasis),
              height var(--t-transition) var(--ease-emphasis),
              opacity var(--t-response) var(--ease);
}
.nav-marker.is-placed { opacity: 1; }
.nav-marker::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: var(--marker-w);
  height: 56%;
  border-radius: 0 var(--marker-w) var(--marker-w) 0;
  background: linear-gradient(var(--accent), var(--violet));
}

.nav-item {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--cs-3);
  width: 100%;
  padding: var(--cs-3);
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--fg-2);
  font-size: var(--fs-body);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  transition: color var(--t-response) var(--ease), transform var(--t-response) var(--ease);
}
.nav-item:hover { color: var(--fg); }
.nav-item:active { transform: scale(0.985); }
.nav-item.is-active { color: var(--fg); font-weight: var(--fw-semibold); }
.nav-item .icon { color: currentColor; transition: transform var(--t-transition) var(--ease-spring); }
.nav-item.is-active .icon { color: var(--accent); transform: scale(1.08); }
.nav-item .chev { margin-left: auto; opacity: 0; transition: opacity var(--t-response) var(--ease); }
.nav-item:hover .chev, .nav-item.is-active .chev { opacity: 0.7; }

.rail-head {
  display: flex;
  align-items: center;
  gap: var(--cs-2);
  padding: 0 var(--cs-3) var(--cs-2);
}
.rail-title {
  margin: 0;
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.rail-count {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--fg-2);
}
.rail-add {
  margin-left: auto;
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--fg-2);
  cursor: pointer;
  transition: color var(--t-response) var(--ease), border-color var(--t-response) var(--ease),
              transform var(--t-response) var(--ease);
}
.rail-add:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-1px); }

.app-rail { display: flex; flex-direction: column; gap: 2px; }

.rail-app {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--cs-3);
  width: 100%;
  padding: var(--cs-2) var(--cs-3);
  border: var(--hairline) solid transparent;
  border-radius: var(--r-md);
  background: transparent;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  min-width: 0;
  transition: background var(--t-response) var(--ease), border-color var(--t-response) var(--ease),
              transform var(--t-response) var(--ease);
}
.rail-app:hover { background: var(--surface-muted); border-color: var(--line); }
.rail-app:active { transform: scale(0.99); }
.rail-app.is-selected { background: var(--surface-muted); border-color: var(--line-strong); }
.rail-app-mark {
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  flex: none;
  border-radius: var(--r-sm);
  background: var(--surface-sunken);
  color: var(--fg-2);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  transition: background var(--t-transition) var(--ease), color var(--t-transition) var(--ease);
}
.rail-app.is-selected .rail-app-mark {
  background: linear-gradient(145deg, var(--accent), var(--violet));
  color: var(--fg-on-accent);
}
.rail-app-body { min-width: 0; flex: 1; }
.rail-app-name {
  display: block;
  font-size: var(--fs-sub);
  font-weight: var(--fw-semibold);
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rail-app-state {
  display: flex;
  align-items: center;
  gap: var(--cs-1);
  font-size: var(--fs-micro);
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rail-empty {
  margin: 0;
  padding: var(--cs-3);
  font-size: var(--fs-sub);
  color: var(--fg-muted);
}

/* The state dot, and the one pulse in the console that repeats: an
   active application is the only thing here that is continuously true. */
.state-dot {
  display: inline-block;
  position: relative;
  width: 0.5rem;
  height: 0.5rem;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--fg-muted);
}
.state-dot.is-active { background: var(--emerald); }
.state-dot.is-registered { background: var(--turquoise); }
.state-dot.is-suspended { background: var(--amber); }
.state-dot.is-active::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--r-pill);
  background: inherit;
  animation: state-ping 2.6s var(--ease) infinite;
}
@keyframes state-ping {
  0% { transform: scale(1); opacity: 0.7; }
  70%, 100% { transform: scale(2.6); opacity: 0; }
}

.nav-scrim { display: none; }

/* =====================================================================
   4. THE WORKSPACE
   ===================================================================== */

.workspace {
  grid-area: work;
  position: relative;
  z-index: 1;
  min-width: 0;
  padding: var(--console-pad);
  display: flex;
  flex-direction: column;
  gap: var(--console-gap);
}

.crumbs {
  display: flex;
  align-items: center;
  gap: var(--cs-1);
  font-size: var(--fs-micro);
  color: var(--fg-muted);
}
.crumbs .here { color: var(--fg-2); font-weight: var(--fw-semibold); }

/* The head of a view: the one place in the console that is allowed to be
   large. */
.page-head { display: flex; align-items: flex-start; gap: var(--cs-4); flex-wrap: wrap; }
.page-mark {
  display: grid;
  place-items: center;
  width: 3.5rem;
  height: 3.5rem;
  flex: none;
  border-radius: var(--r-lg);
  color: var(--fg-on-accent);
  background: linear-gradient(145deg, var(--accent), var(--violet));
  box-shadow: var(--shadow-md), var(--console-glow);
}
.page-head-body { flex: 1 1 18rem; min-width: 0; }
.page-title {
  margin: 0;
  font-size: var(--fs-hero);
  font-weight: var(--fw-heavy);
  letter-spacing: var(--ls-hero);
  line-height: var(--lh-tight);
  color: var(--fg);
  overflow-wrap: anywhere;
}
.page-desc {
  margin: var(--cs-2) 0 0;
  max-width: 64ch;
  color: var(--fg-2);
  font-size: var(--fs-body);
}
.page-actions { margin-left: auto; display: flex; align-items: center; gap: var(--cs-2); flex-wrap: wrap; }

.state-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--cs-2);
  padding: var(--cs-1) var(--cs-3);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-2);
}
.state-pill.is-active { color: var(--emerald-ink); background: var(--emerald-wash); border-color: var(--emerald-line); }
.state-pill.is-registered { color: var(--turquoise-ink); background: var(--turquoise-wash); border-color: var(--line); }
.state-pill.is-suspended { color: var(--amber-ink); background: var(--amber-wash); border-color: var(--amber-line); }

/* The tab strip: the underline moves, the labels do not. */
.tabs {
  display: flex;
  gap: var(--cs-5);
  padding-right: var(--cs-4);
  border-bottom: var(--hairline) solid var(--line);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  position: relative;
  padding: var(--cs-3) 0;
  border: 0;
  background: transparent;
  color: var(--fg-muted);
  font-size: var(--fs-body);
  white-space: nowrap;
  cursor: pointer;
  overflow: hidden;
  transition: color var(--t-response) var(--ease);
}
.tab::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: linear-gradient(90deg, var(--accent), var(--violet));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-transition) var(--ease-emphasis);
}
.tab:hover { color: var(--fg-2); }
.tab.is-active { color: var(--fg); font-weight: var(--fw-semibold); }
.tab.is-active::after { transform: scaleX(1); }

/* =====================================================================
   5. PANELS, FACTS AND FIGURES
   ===================================================================== */

.panel {
  padding: var(--cs-5);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  min-width: 0;
  transition: border-color var(--t-transition) var(--ease);
}
.panel:hover { border-color: var(--line-strong); }
.panel-head {
  display: flex;
  align-items: center;
  gap: var(--cs-3);
  margin-bottom: var(--cs-4);
  flex-wrap: wrap;
}
.panel-title {
  margin: 0;
  font-size: var(--fs-heading);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  color: var(--fg);
}
.panel-note, .panel-link { margin-left: auto; }
.panel-note { font-size: var(--fs-micro); color: var(--fg-muted); }
.panel-link {
  display: inline-flex;
  align-items: center;
  gap: var(--cs-1);
  border: 0;
  background: transparent;
  color: var(--accent);
  font-size: var(--fs-sub);
  cursor: pointer;
  padding: var(--cs-1) 0;
  transition: gap var(--t-response) var(--ease);
}
.panel-link:hover { gap: var(--cs-2); text-decoration: underline; text-underline-offset: 3px; }

.section-head { display: flex; align-items: center; gap: var(--cs-3); margin-bottom: var(--cs-3); flex-wrap: wrap; }
.section-title { margin: 0; font-size: var(--fs-heading); font-weight: var(--fw-bold); }
.section-note { margin-left: auto; font-size: var(--fs-micro); color: var(--fg-muted); }

/* THE FIGURES. A number that changes counts to its new value, so the
   change is visible rather than merely different. The count is driven in
   JavaScript and stops at the real figure; the bar beneath it is the
   same figure as a share of its whole. Neither is ever an estimate. */
.metric-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr));
  gap: var(--cs-3);
}
.metric {
  position: relative;
  overflow: hidden;
  padding: var(--cs-4);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  min-width: 0;
  transition: transform var(--t-transition) var(--ease), box-shadow var(--t-transition) var(--ease),
              border-color var(--t-transition) var(--ease);
}
.metric:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--line-strong); }
.metric-key {
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.metric-value {
  display: flex;
  align-items: baseline;
  gap: var(--cs-2);
  margin-top: var(--cs-1);
  font-size: var(--fs-amount);
  font-weight: var(--fw-heavy);
  letter-spacing: var(--ls-hero);
  line-height: var(--lh-tight);
  color: var(--fg);
  font-variant-numeric: tabular-nums;
  min-width: 0;
}
.metric-value .metric-word { font-size: var(--fs-title); }
.metric-sub { font-size: var(--fs-sub); font-weight: var(--fw-semibold); color: var(--fg-muted); letter-spacing: 0; }
.metric-bar { margin-top: var(--cs-3); height: 4px; border-radius: 3px; background: var(--surface-sunken); overflow: hidden; }
.metric-bar i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent), var(--violet));
  transition: width var(--count-steps) var(--ease-out);
}
.metric.is-health .metric-value { color: var(--emerald-ink); }
.metric.is-held .metric-value { color: var(--amber-ink); }
.metric.is-data .metric-value { color: var(--turquoise-ink); }
.metric-none { font-size: var(--fs-sub); color: var(--fg-muted); }

/* A fact: a key, a value, and -- where the value is an identifier -- the
   control that copies it. */
.fact-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: var(--cs-3); }
.fact {
  display: flex;
  align-items: flex-start;
  gap: var(--cs-3);
  padding: var(--cs-3) var(--cs-4);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-muted);
  min-width: 0;
  transition: border-color var(--t-response) var(--ease);
}
.fact:hover { border-color: var(--line-strong); }
.fact-mark {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  flex: none;
  border-radius: var(--r-sm);
  background: var(--surface-sunken);
  color: var(--fg-2);
}
.fact-mark.is-identity { background: var(--violet-wash); color: var(--violet-ink); }
.fact-mark.is-health { background: var(--emerald-wash); color: var(--emerald-ink); }
.fact-mark.is-data { background: var(--turquoise-wash); color: var(--turquoise-ink); }
.fact-body { min-width: 0; flex: 1; }
.fact-key {
  display: block;
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.fact-value {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--fg);
  overflow-wrap: anywhere;
}
.fact-value.mono { font-family: var(--font-mono); font-size: var(--fs-sub); font-weight: var(--fw-regular); }
.fact-note { display: block; margin-top: 2px; font-size: var(--fs-micro); color: var(--fg-muted); }

.copy-btn {
  display: grid;
  place-items: center;
  width: 1.875rem;
  height: 1.875rem;
  flex: none;
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--fg-muted);
  cursor: pointer;
  transition: color var(--t-response) var(--ease), border-color var(--t-response) var(--ease),
              background var(--t-response) var(--ease), transform var(--t-response) var(--ease);
}
.copy-btn:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-1px); }
.copy-btn.is-copied { color: var(--emerald-ink); border-color: var(--emerald-line); background: var(--emerald-wash); }
.copy-btn.is-copied .icon { animation: copy-pop var(--t-transition) var(--ease-spring); }
@keyframes copy-pop { from { transform: scale(0.5); } to { transform: scale(1); } }

/* =====================================================================
   6. THE LIFECYCLE
   ===================================================================== */

/* Three states, as three cards whose rule fills in. The fill is set after
   paint, so it is seen to travel; a rule that is simply there says only
   that someone drew it. */
.stepper { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--cs-3); }
.step {
  position: relative;
  overflow: hidden;
  padding: var(--cs-4);
  padding-bottom: calc(var(--cs-4) + 3px);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-muted);
  min-width: 0;
  transition: border-color var(--t-transition) var(--ease), background var(--t-transition) var(--ease),
              box-shadow var(--t-transition) var(--ease);
}
.step-node {
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--fg-muted);
}
.step-name {
  display: block;
  margin-top: var(--cs-2);
  font-size: var(--fs-body);
  font-weight: var(--fw-bold);
  color: var(--fg);
}
.step-note { display: block; margin-top: 2px; font-size: var(--fs-sub); color: var(--fg-muted); }
.step-rule {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: var(--line);
  overflow: hidden;
}
.step-rule i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--line-strong);
  transition: width var(--t-arrival) var(--ease-out);
}
.step.is-done { border-color: var(--emerald-line); }
.step.is-done .step-node { border-color: var(--emerald); color: var(--emerald-ink); background: var(--emerald-wash); }
.step.is-done .step-rule i { background: var(--emerald); }
.step.is-current { border-color: var(--accent); background: var(--accent-wash); box-shadow: var(--console-glow); }
.step.is-current .step-node { border-color: var(--accent); color: var(--accent-ink); background: var(--surface); }
.step.is-current .step-rule i { background: linear-gradient(90deg, var(--accent), var(--violet)); }
.step.is-halted { border-color: var(--amber-line); background: var(--amber-wash); box-shadow: none; }
.step.is-halted .step-node { border-color: var(--amber); color: var(--amber-ink); background: var(--surface); }
.step.is-halted .step-rule i { background: var(--amber); }
.step.is-future { opacity: 0.72; }

/* =====================================================================
   7. THE TIMELINE
   ===================================================================== */

.timeline { display: flex; flex-direction: column; position: relative; }
.tl-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--cs-3);
  align-items: start;
  padding: var(--cs-3) 0;
  border-bottom: var(--hairline) solid var(--line);
  transition: background var(--t-response) var(--ease);
}
.tl-row:last-child { border-bottom: 0; }
.tl-node {
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--surface-sunken);
  color: var(--fg-2);
}
.tl-node.is-ok { background: var(--emerald-wash); color: var(--emerald-ink); }
.tl-node.is-warn { background: var(--amber-wash); color: var(--amber-ink); }
.tl-node.is-failed { background: var(--danger-wash); color: var(--danger-ink); }
.tl-title { display: block; font-size: var(--fs-body); font-weight: var(--fw-semibold); color: var(--fg); }
.tl-desc { display: block; margin-top: 2px; font-size: var(--fs-sub); color: var(--fg-muted); }
.tl-when { display: block; font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--fg-2); white-space: nowrap; text-align: right; }
.tl-date { display: block; font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--fg-muted); white-space: nowrap; text-align: right; }
.tl-detail { margin-top: var(--cs-2); }
.tl-detail > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--cs-1);
  font-size: var(--fs-micro);
  color: var(--fg-muted);
  cursor: pointer;
  list-style: none;
}
.tl-detail > summary::-webkit-details-marker { display: none; }
.tl-detail > summary .chev { transition: transform var(--t-response) var(--ease); }
.tl-detail[open] > summary .chev { transform: rotate(180deg); }
.detail-list {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--cs-1) var(--cs-3);
  margin: var(--cs-2) 0 0;
  padding: var(--cs-3);
  border-radius: var(--r-sm);
  background: var(--surface-muted);
  font-size: var(--fs-micro);
}
.detail-list dt { color: var(--fg-muted); }
.detail-list dd { margin: 0; font-family: var(--font-mono); overflow-wrap: anywhere; }

/* =====================================================================
   8. THE BUTTON FAMILY
   ===================================================================== */

/* One family: primary, secondary, ghost, destructive, icon. Every one of
   them lifts on hover, settles on press, and carries a ripple from the
   point of contact. The ripple element is appended in JavaScript and
   removes itself; nothing here depends on it existing. */
.console .btn,
.gate .btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--cs-2);
  height: 2.5rem;
  padding: 0 var(--cs-4);
  border: var(--hairline) solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--fg);
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-tight);
  cursor: pointer;
  white-space: nowrap;
  transition: transform var(--t-response) var(--ease), box-shadow var(--t-transition) var(--ease),
              background var(--t-response) var(--ease), border-color var(--t-response) var(--ease),
              color var(--t-response) var(--ease);
}
.console .btn:hover, .gate .btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); border-color: var(--fg-muted); }
.console .btn:active, .gate .btn:active { transform: translateY(0) scale(0.98); }
.console .btn-primary, .gate .btn-primary {
  background: linear-gradient(145deg, var(--accent), var(--accent-hover));
  border-color: transparent;
  color: var(--accent-fg);
}
.console .btn-primary:hover, .gate .btn-primary:hover { box-shadow: var(--shadow-md), var(--console-glow); }
.console .btn-secondary { background: var(--surface); color: var(--fg); }
.console .btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--fg-2);
}
.console .btn-ghost:hover { background: var(--surface-muted); color: var(--fg); box-shadow: none; border-color: transparent; }
/* DESTRUCTIVE: tinted and outlined, never a filled slab. It has to read
   as serious from across a desk without being the loudest thing on the
   screen -- an administrator presses it on purpose, not by eye. */
.console .btn-danger, .gate .btn-danger {
  background: var(--danger-wash);
  border-color: var(--danger);
  color: var(--danger-ink);
}
.console .btn-danger:hover { background: var(--danger-wash); border-color: var(--danger-solid); box-shadow: var(--shadow-md); }
.console .btn-sm { height: 2rem; padding: 0 var(--cs-3); font-size: var(--fs-micro); border-radius: var(--r-sm); }
.console .btn-hero { height: 2.875rem; padding: 0 var(--cs-5); font-size: var(--fs-body); }
.console .btn-block { width: 100%; }
.console .btn[disabled], .gate .btn[disabled] { opacity: 0.45; pointer-events: none; }
/* BUSY: a ring spins BESIDE the label, and the control stops accepting a
   second press. The label itself changes word -- "Suspending…" -- because a
   spinner alone says that something is happening and not what. A button
   that still looks pressable while its request is in flight gets pressed
   twice, and the second press is the one nobody meant. */
.console .btn.is-busy, .gate .btn.is-busy { pointer-events: none; }
.console .btn.is-busy::before, .gate .btn.is-busy::before {
  content: "";
  width: 0.875rem;
  height: 0.875rem;
  flex: none;
  border-radius: var(--r-pill);
  border: 2px solid var(--line-strong);
  border-top-color: var(--fg-2);
  animation: btn-spin 0.7s linear infinite;
}
.console .btn-primary.is-busy::before { border-color: var(--accent-wash); border-top-color: var(--accent-fg); }
.console .btn-danger.is-busy::before { border-color: var(--danger-wash); border-top-color: var(--danger-ink); }
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* THE ONE ACTION. The context panel's lifecycle control is the only
   full-width, gradient-filled button in the console, and there is never
   more than one of it on screen: an administrator should be able to find
   the thing they came to do without reading. A destructive one is tinted
   and outlined instead -- the same rule as everywhere else, at a larger
   size. It carries its own `.btn-hero` class rather than joining the `.btn`
   family, so it is styled here in full. */
.btn-hero {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cs-3);
  width: 100%;
  min-height: 2.875rem;
  padding: var(--cs-3) var(--cs-4);
  border: var(--hairline) solid transparent;
  border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--accent), var(--violet));
  color: var(--accent-fg);
  font: inherit;
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  text-align: left;
  cursor: pointer;
  box-shadow: var(--shadow-accent);
  transition: transform var(--t-response) var(--ease), box-shadow var(--t-transition) var(--ease),
              background var(--t-response) var(--ease);
}
.btn-hero:hover { transform: translateY(-1px); box-shadow: var(--shadow-accent), var(--console-glow); }
.btn-hero:active { transform: translateY(0) scale(0.99); }
.btn-hero .go { transition: transform var(--t-transition) var(--ease-spring); flex: none; }
.btn-hero:hover .go { transform: translateX(3px); }
.btn-hero[disabled] { opacity: 0.55; cursor: not-allowed; transform: none; box-shadow: none; }
.btn-hero.is-danger {
  background: var(--danger-wash);
  border-color: var(--danger);
  color: var(--danger-ink);
  box-shadow: none;
}
.btn-hero.is-danger:hover { box-shadow: var(--shadow-md); border-color: var(--danger-solid); }

.ripple {
  position: absolute;
  border-radius: var(--r-pill);
  transform: scale(0);
  background: var(--console-ripple);
  pointer-events: none;
  animation: ripple-out 0.55s var(--ease-out) forwards;
}
@keyframes ripple-out { to { transform: scale(2.6); opacity: 0; } }

/* The enrolment switch. The knob springs; the track tells the truth in a
   word beside it, because a coloured track alone is not a statement. */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--cs-3);
  padding: var(--cs-2) var(--cs-3);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--t-response) var(--ease);
}
.switch:hover { border-color: var(--line-strong); }
.switch-track {
  position: relative;
  width: 2.625rem;
  height: 1.5rem;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--surface-sunken);
  box-shadow: inset 0 0 0 var(--hairline) var(--line-strong);
  transition: background var(--t-transition) var(--ease), box-shadow var(--t-transition) var(--ease);
}
.switch-knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: var(--r-pill);
  background: var(--fg-muted);
  transition: transform var(--t-transition) var(--ease-spring), background var(--t-transition) var(--ease);
}
.switch[aria-pressed="true"] .switch-track { background: var(--emerald-wash); box-shadow: inset 0 0 0 var(--hairline) var(--emerald); }
.switch[aria-pressed="true"] .switch-knob { transform: translateX(1.125rem); background: var(--emerald); }
.switch-word { font-size: var(--fs-sub); font-weight: var(--fw-semibold); color: var(--amber-ink); }
.switch[aria-pressed="true"] .switch-word { color: var(--emerald-ink); }
.switch[disabled] { opacity: 0.5; pointer-events: none; }

/* An identifier is monospace wherever it appears, so a thing that can be
   copied looks like a thing that can be copied. */
.mono { font-family: var(--font-mono); font-size: var(--fs-sub); letter-spacing: 0; }

/* A disclosure: the technical detail an administrator may want and should
   not have to read first. */
.disclose {
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-muted);
  overflow: hidden;
}
.disclose > summary {
  display: flex;
  align-items: center;
  gap: var(--cs-3);
  padding: var(--cs-3) var(--cs-4);
  cursor: pointer;
  font-size: var(--fs-sub);
  font-weight: var(--fw-semibold);
  list-style: none;
}
.disclose > summary::-webkit-details-marker { display: none; }
.disclose > summary::marker { content: ""; }
.disclose > summary .chev { margin-left: auto; transition: transform var(--t-response) var(--ease); }
.disclose[open] > summary .chev { transform: rotate(180deg); }
.disclose > .tech-body { padding: 0 var(--cs-4) var(--cs-4); display: flex; flex-direction: column; gap: var(--cs-3); }
.ctx-sep { height: var(--hairline); background: var(--line); border: 0; margin: 0; }

/* =====================================================================
   9. TABLES, CHIPS AND THE CONTEXTUAL PANEL
   ===================================================================== */

.table-wrap { overflow-x: auto; border: var(--hairline) solid var(--line); border-radius: var(--r-md); }
.console .data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sub); }
.console .data-table th {
  position: sticky;
  top: 0;
  text-align: left;
  padding: var(--cs-3) var(--cs-4);
  background: var(--surface-muted);
  border-bottom: var(--hairline) solid var(--line);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
  white-space: nowrap;
}
.console .data-table td { padding: var(--cs-3) var(--cs-4); border-bottom: var(--hairline) solid var(--line); vertical-align: middle; }
.console .data-table tr:last-child td { border-bottom: 0; }
.console .data-table tbody tr { transition: background var(--t-response) var(--ease); }
.console .data-table tbody tr:hover { background: var(--surface-muted); }
.console .data-table .mono { font-family: var(--font-mono); font-size: var(--fs-micro); overflow-wrap: anywhere; }

.console .chip {
  display: inline-flex;
  align-items: center;
  gap: var(--cs-1);
  padding: 2px var(--cs-2);
  border-radius: var(--r-pill);
  background: var(--surface-sunken);
  color: var(--fg-2);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}
.console .chip.is-ok { background: var(--emerald-wash); color: var(--emerald-ink); }
.console .chip.is-warn { background: var(--amber-wash); color: var(--amber-ink); }
.console .chip.is-failed { background: var(--danger-wash); color: var(--danger-ink); }
.console .chip.is-identity { background: var(--violet-wash); color: var(--violet-ink); }
.console .chip.is-data { background: var(--turquoise-wash); color: var(--turquoise-ink); }

.console-context {
  grid-area: ctx;
  z-index: 1;
  position: sticky;
  top: var(--console-head-h);
  max-height: calc(100dvh - var(--console-head-h));
  overflow-y: auto;
  padding: var(--console-pad) var(--cs-4);
  border-left: var(--hairline) solid var(--line);
  background: var(--console-ctx-bg);
  min-width: 0;
}
.ctx-flow { display: flex; flex-direction: column; gap: var(--cs-5); }
.ctx-block { display: flex; flex-direction: column; gap: var(--cs-2); min-width: 0; }
.ctx-title {
  margin: 0;
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.ctx-label {
  display: flex;
  align-items: center;
  gap: var(--cs-2);
  margin: 0;
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.ctx-desc { margin: 0; font-size: var(--fs-sub); color: var(--fg-2); }
.ctx-hint { margin: 0; font-size: var(--fs-sub); color: var(--fg-muted); line-height: var(--lh-body); }

.quick { display: flex; flex-direction: column; gap: var(--cs-2); }
.quick-btn {
  display: flex;
  align-items: center;
  gap: var(--cs-2);
  width: 100%;
  padding: var(--cs-2) var(--cs-3);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--fg-2);
  font-size: var(--fs-sub);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  position: relative;
  transition: color var(--t-response) var(--ease), border-color var(--t-response) var(--ease),
              transform var(--t-response) var(--ease);
}
.quick-btn:hover { color: var(--fg); border-color: var(--accent); transform: translateY(-1px); }
.quick-btn .icon { flex: none; }

.enrol-grid { display: grid; gap: var(--cs-3); }

/* =====================================================================
   10. STATES: LOADING, EMPTY, FAILED
   ===================================================================== */

.skeleton { display: flex; flex-direction: column; gap: var(--cs-2); }
.sk {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-sm);
  background: var(--skeleton);
}
.sk::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--skeleton-shine), transparent);
  animation: sk-shimmer var(--shimmer-t) infinite;
}
@keyframes sk-shimmer { to { transform: translateX(100%); } }
.sk-row { height: 2.5rem; }
.sk-40 { height: 0.75rem; width: 40%; }
.sk-60 { height: 0.75rem; width: 60%; }
.sk-wide { width: 100%; }

.state-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--cs-2);
  padding: var(--cs-7) var(--cs-4);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-muted);
  text-align: center;
}
.state-block h3 { margin: 0; font-size: var(--fs-heading); font-weight: var(--fw-bold); }
.state-block p { margin: 0; max-width: 54ch; font-size: var(--fs-sub); color: var(--fg-muted); }
.state-block-mark {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--r-pill);
  background: var(--surface-sunken);
  color: var(--fg-muted);
}
.state-block.is-failed { border-color: var(--danger); background: var(--danger-wash); }
.state-block.is-failed .state-block-mark { background: var(--danger-wash); color: var(--danger-ink); }

/* =====================================================================
   11. ARRIVAL
   ===================================================================== */

/* A view arrives once, from just below where it will rest. Cards inside
   it arrive in order, 55ms apart, so the eye is led down the page rather
   than ambushed by all of it at once. */
.anim-view { animation: console-rise var(--t-arrival) var(--ease-out) both; }
.anim-panel { animation: console-rise var(--t-arrival) var(--ease-out) both; }
@keyframes console-rise {
  from { opacity: 0; transform: translateY(var(--lift-enter)); }
  to   { opacity: 1; transform: none; }
}
.stagger > * { animation: console-rise var(--t-arrival) var(--ease-out) both; }
.stagger > *:nth-child(1) { animation-delay: calc(var(--stagger-step) * 0); }
.stagger > *:nth-child(2) { animation-delay: calc(var(--stagger-step) * 1); }
.stagger > *:nth-child(3) { animation-delay: calc(var(--stagger-step) * 2); }
.stagger > *:nth-child(4) { animation-delay: calc(var(--stagger-step) * 3); }
.stagger > *:nth-child(5) { animation-delay: calc(var(--stagger-step) * 4); }
.stagger > *:nth-child(n+6) { animation-delay: calc(var(--stagger-step) * 5); }

/* A panel below the fold arrives when it is reached, not while nobody is
   looking at it. `is-seen` is set by an observer; without JavaScript the
   panel is simply visible, which is the correct failure. */
.reveal { opacity: 0; transform: translateY(0.75rem); }
.reveal.is-seen {
  opacity: 1;
  transform: none;
  transition: opacity var(--t-arrival) var(--ease-out), transform var(--t-arrival) var(--ease-out);
}

/* =====================================================================
   12. TOASTS, MODALS AND THE SCRIM
   ===================================================================== */

.toast-stack {
  position: fixed;
  right: var(--cs-4);
  bottom: var(--cs-4);
  z-index: 90;
  display: flex;
  flex-direction: column;
  gap: var(--cs-2);
  max-width: min(26rem, calc(100vw - var(--cs-6)));
}
.console .toast {
  display: flex;
  align-items: center;
  gap: var(--cs-3);
  padding: var(--cs-3) var(--cs-4);
  border: var(--hairline) solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  box-shadow: var(--shadow-dock);
  font-size: var(--fs-sub);
  animation: toast-rise var(--t-arrival) var(--ease-spring) both;
}
@keyframes toast-rise {
  from { opacity: 0; transform: translateY(0.75rem); }
  to   { opacity: 1; transform: none; }
}

.scrim-layer {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  padding: var(--cs-4);
  background: var(--scrim);
  backdrop-filter: blur(var(--blur-overlay));
  -webkit-backdrop-filter: blur(var(--blur-overlay));
  animation: console-fade var(--t-transition) var(--ease) both;
}
@keyframes console-fade { from { opacity: 0; } to { opacity: 1; } }
.console .modal {
  width: min(32rem, 100%);
  max-height: calc(100dvh - var(--cs-7));
  overflow-y: auto;
  padding: var(--cs-5);
  border: var(--hairline) solid var(--line-strong);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--shadow-dock);
  animation: console-pop var(--t-transition) var(--ease-spring) both;
}
.modal-title { margin: 0 0 var(--cs-2); font-size: var(--fs-title); font-weight: var(--fw-heavy); letter-spacing: var(--ls-tight); }
.modal-actions { display: flex; gap: var(--cs-2); justify-content: flex-end; margin-top: var(--cs-5); flex-wrap: wrap; }

/* =====================================================================
   13. THE SIGNED-OUT GATE
   ===================================================================== */

.gate {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: var(--cs-5);
  background: var(--console-bg);
  overflow-x: clip;
  position: relative;
}
.gate::before {
  content: "";
  position: fixed;
  inset: -20% -10% auto;
  height: 60vh;
  z-index: 0;
  pointer-events: none;
  filter: blur(70px);
  background:
    radial-gradient(40% 50% at 30% 30%, var(--console-aura-1) 0%, transparent 70%),
    radial-gradient(34% 44% at 70% 20%, var(--console-aura-2) 0%, transparent 72%);
  animation: console-drift var(--t-ambient) var(--ease) infinite alternate;
}
.gate-card {
  position: relative;
  z-index: 1;
  width: min(30rem, 100%);
  padding: var(--cs-6);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--shadow-dock);
  animation: console-rise var(--t-arrival) var(--ease-out) both;
}
.gate-eyebrow {
  margin: 0 0 var(--cs-2);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--accent);
}
.gate-title { margin: 0; font-size: var(--fs-title); font-weight: var(--fw-heavy); letter-spacing: var(--ls-tight); }
.gate-desc { margin: var(--cs-2) 0 var(--cs-5); font-size: var(--fs-sub); color: var(--fg-muted); }
.gate-body { display: flex; flex-direction: column; gap: var(--cs-4); }
.qr-frame {
  display: grid;
  place-items: center;
  padding: var(--cs-4);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-muted);
}

/* =====================================================================
   14. THE ARRANGEMENTS
   Five, each a change of structure rather than a change of size.
   ===================================================================== */

/* Very wide: the console stops growing and centres, because a line of
   running text 200 characters long is not readable at any size. */
@media (min-width: 120rem) {
  .console {
    grid-template-columns:
      minmax(0, 1fr) var(--console-nav)
      minmax(0, calc(var(--console-max) - var(--console-nav) - var(--console-context)))
      var(--console-context) minmax(0, 1fr);
    grid-template-areas:
      "head head head head head"
      ".    nav  work ctx  .";
  }
}

/* Laptop: the context panel narrows first, because the workspace is
   where the work happens. */
@media (max-width: 90rem) {
  :root { --console-context: 19rem; --console-nav: 15rem; --console-pad: var(--cs-5); }
  .page-title { font-size: var(--fs-amount); }
}

/* Tablet: the context panel MOVES below the workspace, full width, in
   two columns. It is not hidden: the controls it carries are the ones an
   administrator came for. */
@media (max-width: 75rem) {
  .brand-sub { display: none; }
  .console {
    grid-template-columns: var(--console-nav) minmax(0, 1fr);
    grid-template-areas:
      "head head"
      "nav  work"
      "nav  ctx";
  }
  .console-context {
    position: static;
    max-height: none;
    border-left: 0;
    border-top: var(--hairline) solid var(--line);
    padding: var(--cs-5) var(--console-pad) var(--cs-7);
  }
  .ctx-flow {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
    gap: var(--cs-5);
    align-items: start;
  }
}

/* Narrow: the navigation becomes a drawer opened from the header, and
   the application rail goes with it, because it is navigation too. */
@media (max-width: 60rem) {
  .console {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "head"
      "work"
      "ctx";
  }
  .console-nav {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 70;
    width: min(20rem, 86vw);
    max-height: none;
    transform: translateX(-100%);
    transition: transform var(--t-transition) var(--ease-emphasis);
    box-shadow: var(--shadow-dock);
  }
  .console-nav.is-open { transform: none; }
  .nav-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 65;
    background: var(--scrim);
    animation: console-fade var(--t-response) var(--ease) both;
  }
  .nav-toggle { display: grid; }
  .cmd { flex: 1 1 auto; max-width: none; }
  .cmd-hint { display: none; }
}

/* Mobile: one column, the stepper turns vertical, and every table becomes
   a list of labelled rows rather than something to scroll sideways. */
@media (max-width: 40rem) {
  :root { --console-pad: var(--cs-4); --console-gap: var(--cs-4); }

  .console-head { flex-wrap: wrap; row-gap: var(--cs-2); padding: var(--cs-3) var(--cs-4); }
  .brand-sub { display: none; }
  .cmd { order: 3; flex: 1 0 100%; }
  .identity-name { display: none; }
  /* The label goes; "System / Light / Dark" is its own label at this size. */
  .console-head .appearance-inline-label { display: none; }
  .console-head .appearance-inline { gap: 0; }

  .page-head { gap: var(--cs-3); }
  .page-mark { width: 2.75rem; height: 2.75rem; }
  .page-title { font-size: var(--fs-title); }
  .page-actions { margin-left: 0; width: 100%; }

  .metric-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--cs-2); }
  .metric { padding: var(--cs-3); }
  .metric-key { min-height: 2.6em; }
  .metric-value { font-size: var(--fs-title); }

  .stepper { grid-template-columns: minmax(0, 1fr); }
  .panel { padding: var(--cs-4); border-radius: var(--r-md); }
  .fact-grid { grid-template-columns: minmax(0, 1fr); }

  .tl-row { grid-template-columns: 1.75rem minmax(0, 1fr); }
  .tl-when, .tl-date { grid-column: 2; text-align: left; }

  /* A table that scrolls sideways on a phone is a table nobody reads.
     Each row becomes a card and each cell keeps its own heading. */
  .data-table.is-stacking,
  .data-table.is-stacking thead,
  .data-table.is-stacking tbody,
  .data-table.is-stacking tr,
  .data-table.is-stacking td { display: block; width: 100%; }
  .data-table.is-stacking thead { display: none; }
  .data-table.is-stacking tr {
    border-bottom: var(--hairline) solid var(--line);
    padding: var(--cs-2) 0;
  }
  .data-table.is-stacking td {
    display: grid;
    grid-template-columns: 6.5rem minmax(0, 1fr);
    gap: var(--cs-3);
    justify-items: start;
    align-items: center;
    border: 0;
    padding: var(--cs-2) var(--cs-4);
  }
  .data-table.is-stacking td .mono {
    font-size: var(--fs-micro);
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .data-table.is-stacking td::before {
    content: attr(data-head);
    align-self: start;
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-wide);
    text-transform: uppercase;
    color: var(--fg-muted);
  }

  .toast-stack { right: var(--cs-3); left: var(--cs-3); bottom: var(--cs-3); max-width: none; }
  .console .modal { padding: var(--cs-4); }
}

/* Announced, never shown. Every live region and every label the console
   writes for a screen reader uses this; without it they are rendered on
   screen beside the control they describe. */
.sr-live {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* =====================================================================
   15. REDUCED MOTION
   Both halves -- the durations AND the keyframes. Shortening an
   animation that repeats forever changes nothing, so the three that
   repeat are stopped outright.
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  .console *,
  .console *::before,
  .console *::after,
  .gate *,
  .gate *::before,
  .gate *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
  .sk::after { animation: none !important; }
  .state-dot.is-active::after { animation: none !important; }
  .brand-mark::after { animation: none !important; }
  .console::before, .gate::before { animation: none !important; }
  .reveal { opacity: 1; transform: none; }
}
