/* ============================================================
   EYT Studio v2 layer
   Applies the teardown prescription on top of app.css.
   Loaded AFTER app.css so it wins on the cascade.

   What this file changes, and why:
     1  the brand mark replaces the CSS-only wordmark
     2  sidebar collapses to icons, control lives IN the rail
     3  the arc meter, the signature capacity primitive
     4  the KPI card row becomes a metric row that drives a chart
     5  Playfair actually runs, at 34px, in three places only
     6  one live ochre, spent on exactly one semantic
     7  asymmetry in layout, never in rows
   ============================================================ */

:root {
  /* the focal size. Its job is to be the number the eye lands on
     first. One per screen. Never a row of four. */
  --fs-focal: 34px;

  /* the live colour. Spent on ONE semantic in the entire product:
     the class that is running right now. Nothing else, ever.
     Deliberately hotter than --amber so it never reads as a warning. */
  --live: #cd6a17;
  --live-050: #fbeee2;

  /* arc meter ring palette, sampled from the mark itself */
  --arc-1: #5b3d75;
  --arc-2: #404a75;
  --arc-3: #285574;
  --arc-4: #568c9b;
  --arc-empty: #e7e0d6;

  --rail-w: 66px;
}

/* ============================================================
   1 + 2. Brand and the collapsing rail
   ============================================================ */

/* the brand stays pinned. A 21-item rail scrolls, and a mark that
   scrolls out of its own sidebar is how a logo ends up overlapped. */
.sidebar__brand {
  padding: 4px 6px 14px;
  gap: 9px;
  min-width: 0;
  position: sticky;
  top: -16px;
  z-index: 3;
  background: linear-gradient(180deg, #fffdfa 76%, rgba(255, 253, 250, 0));
  margin: -16px -14px 0;
  padding-left: 20px;
  padding-right: 20px;
  padding-top: 20px;
}
.app.rail .sidebar__brand {
  margin-left: -10px;
  margin-right: -10px;
  padding-left: 10px;
  padding-right: 10px;
}
.brandmark {
  width: 30px;
  height: 30px;
  flex: none;
  display: block;
}
.sidebar__brand .wordmark {
  min-width: 0;
  overflow: hidden;
}
.wordmark--lg .eyt {
  font-size: 23px;
}
.wordmark--lg .sub {
  font-size: 16px;
}

/* the collapse control sits in the rail, under the nav, so it can
   never overlap the mark the way a floating toggle does */
.rail-toggle {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 11px;
  border-radius: var(--r-sm);
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 500;
  width: 100%;
  text-align: left;
  transition:
    background 0.12s,
    color 0.12s;
}
.rail-toggle:hover {
  background: var(--surface-2);
  color: var(--ink);
}
.rail-toggle svg {
  width: 18px;
  height: 18px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  transition: transform 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}

.app {
  transition: grid-template-columns 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
.app.rail .sidebar {
  padding-left: 10px;
  padding-right: 10px;
}
.app.rail {
  grid-template-columns: var(--rail-w) 1fr;
}
/* everything textual in the rail collapses to zero width rather than
   display:none, so nothing can reflow on top of the mark mid-transition */
.app.rail .wordmark,
.app.rail .nav-item span,
.app.rail .nav-section,
.app.rail .sidebar__foot,
.app.rail .rail-toggle span {
  width: 0;
  opacity: 0;
  overflow: hidden;
  white-space: nowrap;
  pointer-events: none;
}
.app.rail .nav-section {
  height: 8px;
  padding: 0;
}
.app.rail .nav-item,
.app.rail .rail-toggle {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}
.app.rail .nav-item .count {
  position: absolute;
  top: 3px;
  right: 3px;
  margin: 0;
  padding: 0;
  width: 7px;
  height: 7px;
  min-width: 0;
  font-size: 0;
  background: var(--plum);
  border-radius: 50%;
}
.app.rail .nav-item.active::before {
  left: -10px;
}
.app.rail .rail-toggle svg {
  transform: rotate(180deg);
}
.app.rail .sidebar__brand {
  justify-content: center;
  padding-bottom: 14px;
}

/* ============================================================
   3. The arc meter
   Concentric open arcs, one per quarter of capacity, filling
   clockwise. Brand geometry doing a job. Scales 18px to 96px on
   one drawing because it is stroked, not filled.
   ============================================================ */

.arcm {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}
.arcm__ring {
  flex: none;
  display: block;
  width: 26px;
  height: 26px;
  overflow: visible;
}
.arcm__ring circle {
  fill: none;
  stroke-linecap: round;
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
}
.arcm__ring .bg {
  stroke: var(--arc-empty);
}
/* at the large size the meter is block level. An inline-flex box that
   tall hangs below its own line box and lands on the text under it. */
.arcm--lg {
  display: flex;
  gap: 14px;
}
.arcm--lg .arcm__ring {
  width: 64px;
  height: 64px;
}
.arcm--lg .arcm__n {
  font-size: 20px;
}
.arcm--sm .arcm__ring {
  width: 23px;
  height: 23px;
}
.arcm__n {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.arcm__n .of {
  color: var(--muted);
  font-weight: 500;
}
.arcm--full .arcm__n {
  color: var(--ink);
}

/* the one live semantic */
.is-live .arcm__ring .lead {
  stroke: var(--live);
}
.pill--live {
  background: var(--live-050);
  color: #8f480d;
  border: 1px solid #f0d9c0;
  font-weight: 600;
}
.pill--live::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--live);
  margin-right: 6px;
  animation: livepulse 2.4s ease-in-out infinite;
}
@keyframes livepulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}
tr.is-live > td:first-child {
  box-shadow: inset 3px 0 0 var(--live);
}

/* the EYT nouns, used where the noun is the thing being read.
   Muted so the row still scans by text, not by icon soup. */
.classcell {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}
.classcell__i {
  width: 17px;
  height: 17px;
  flex: none;
  stroke: var(--plum);
  fill: none;
  opacity: 0.6;
}
tr.is-live .classcell__i {
  stroke: var(--live);
  opacity: 1;
}

/* ============================================================
   4. The metric row
   Not four equal cards. A row of read-outs that IS the chart's
   control: click one, the chart below redraws. The wide first
   column is the number that actually runs the studio.
   ============================================================ */

.metricrow {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  border-bottom: 0;
  overflow: hidden;
}
.metric {
  border: 0;
  border-left: 1px solid var(--line);
  background: none;
  padding: 15px 18px 13px;
  text-align: left;
  position: relative;
  transition: background 0.14s;
  min-width: 0;
}
.metric:first-child {
  border-left: 0;
}
.metric:hover {
  background: var(--surface-2);
}
.metric__value,
.metric__meta {
  display: block;
}
.metric__label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.01em;
  margin-bottom: 7px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.metric__label svg {
  width: 14px;
  height: 14px;
  flex: none;
  opacity: 0.7;
}
.metric__value {
  font-size: 26px;
  font-weight: 650;
  line-height: 1.05;
  letter-spacing: -0.022em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
.metric__meta {
  font-size: 11px;
  color: var(--muted);
  margin-top: 5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.metric::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--plum);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.24s cubic-bezier(0.22, 1, 0.36, 1);
}
.metric.on::after {
  transform: scaleX(1);
}
.metric.on .metric__label {
  color: var(--plum);
}

/* the focal number. Playfair, 34px, exactly one on the screen:
   whichever metric is selected. */
.metric.on .metric__value {
  font-family: var(--font-brand);
  font-size: var(--fs-focal);
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.01em;
}

.metricchart {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  padding: 16px 18px 14px;
}
.metricchart__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.metricchart__title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.metricchart__note {
  font-size: 12px;
  color: var(--muted);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.metricchart svg {
  width: 100%;
  height: 132px;
  display: block;
  overflow: visible;
}
.metricchart .bar {
  fill: var(--plum);
  opacity: 0.22;
  transition:
    height 0.3s cubic-bezier(0.22, 1, 0.36, 1),
    y 0.3s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.14s;
}
.metricchart .bar:hover {
  opacity: 0.4;
}
.metricchart .bar.last {
  opacity: 0.62;
}
.metricchart .axis {
  fill: var(--muted);
  font-size: 10.5px;
  font-family: var(--font-ui);
}
.metricchart .rule {
  stroke: var(--line);
  stroke-width: 1;
}

/* Every remaining KPI row in the product inherits the same register:
   no card boxes, hairline separators, first column wide. One rule
   rather than 29 hand edits, and no row of four equal cards survives
   anywhere in the product. */
.kpi-grid,
.grid.cols-3:has(> .kpi),
.grid.cols-4:has(> .kpi) {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr;
  gap: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.kpi-grid {
  grid-template-columns: 1.5fr 1fr 1fr 1fr;
}
.kpi-grid > .kpi,
.grid.cols-3:has(> .kpi) > .kpi,
.grid.cols-4:has(> .kpi) > .kpi {
  background: none;
  border: 0;
  border-left: 1px solid var(--line);
  border-radius: 0;
  box-shadow: none;
  padding: 15px 18px 14px;
  min-width: 0;
}
.kpi-grid > .kpi:first-child,
.grid.cols-3:has(> .kpi) > .kpi:first-child,
.grid.cols-4:has(> .kpi) > .kpi:first-child {
  border-left: 0;
}
.grid.cols-3:has(> .kpi) > .kpi:nth-child(4),
.grid.cols-4:has(> .kpi) > .kpi:nth-child(5) {
  border-left: 0;
}
.grid.cols-3:has(> .kpi) > .kpi:nth-child(n + 4),
.grid.cols-4:has(> .kpi) > .kpi:nth-child(n + 5) {
  border-top: 1px solid var(--line);
}
.kpi__value {
  font-size: 26px;
  font-weight: 650;
  letter-spacing: -0.022em;
  color: var(--ink-2);
}
.kpi-grid > .kpi:first-child .kpi__value,
.grid.cols-3:has(> .kpi) > .kpi:first-child .kpi__value,
.grid.cols-4:has(> .kpi) > .kpi:first-child .kpi__value {
  font-family: var(--font-brand);
  font-size: var(--fs-focal);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
@media (max-width: 1180px) {
  .kpi-grid,
  .grid.cols-3:has(> .kpi),
  .grid.cols-4:has(> .kpi) {
    grid-template-columns: 1fr 1fr;
  }
}
@media (max-width: 720px) {
  .kpi-grid,
  .grid.cols-3:has(> .kpi),
  .grid.cols-4:has(> .kpi) {
    grid-template-columns: 1fr;
  }
  .kpi-grid > .kpi,
  .grid.cols-3:has(> .kpi) > .kpi,
  .grid.cols-4:has(> .kpi) > .kpi {
    border-left: 0;
    border-top: 1px solid var(--line);
  }
}

/* the consequence sentence. Every number carries one line of plain
   English saying what it means. This is the product's voice. */
.consequence {
  font-size: 12.5px;
  color: var(--ink-2);
  line-height: 1.5;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.consequence b {
  font-weight: 600;
  color: var(--ink);
}

/* ============================================================
   5. Playfair, in exactly three places
   ============================================================ */

.focal {
  font-family: var(--font-brand);
  font-size: var(--fs-focal);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.1;
  color: var(--ink);
}
/* the class name on a booking or roster header */
.classname {
  font-family: var(--font-brand);
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.005em;
  line-height: 1.15;
  color: var(--ink);
}
/* Playfair is barred from anything that repeats. A front desk reads
   rows all day and rows stay Inter. */
td .focal,
td .classname,
th .focal,
.metric:not(.on) .metric__value {
  font-family: var(--font-ui);
}

/* ============================================================
   7. Asymmetry in layout, never in rows
   ============================================================ */

.grid.cols-wide3 {
  display: grid;
  grid-template-columns: 1.55fr 1fr 1fr;
  gap: 14px;
}

@media (max-width: 1180px) {
  .metricrow {
    grid-template-columns: 1fr 1fr;
  }
  .metric:nth-child(3) {
    border-left: 0;
  }
  .metric:nth-child(n + 3) {
    border-top: 1px solid var(--line);
  }
  .grid.cols-wide3 {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 720px) {
  .metricrow {
    grid-template-columns: 1fr;
  }
  .metric {
    border-left: 0;
    border-top: 1px solid var(--line);
  }
  .metric:first-child {
    border-top: 0;
  }
}

/* the mark leads the landing page, above the wordmark */
.hero-mark {
  display: block;
  margin: 0 auto 18px;
  width: 92px;
  height: 92px;
}
@media (max-width: 600px) {
  .hero-mark {
    width: 68px;
    height: 68px;
  }
}

/* ============================================================
   Narrow screens. The preview is a desktop product, but a topbar
   that runs 135px past the viewport is the kind of detail that
   reads as unfinished, so it is handled rather than ignored.
   ============================================================ */

@media (max-width: 860px) {
  .app {
    grid-template-columns: var(--rail-w) 1fr;
  }
  .app .wordmark,
  .app .nav-item > span,
  .app .nav-section,
  .app .sidebar__foot,
  .app .rail-toggle span {
    width: 0;
    opacity: 0;
    overflow: hidden;
    white-space: nowrap;
    pointer-events: none;
  }
  .app .nav-item,
  .app .rail-toggle {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }
  .app .sidebar {
    padding-left: 10px;
    padding-right: 10px;
  }
  .app .sidebar__brand {
    justify-content: center;
    margin-left: -10px;
    margin-right: -10px;
    padding-left: 10px;
    padding-right: 10px;
  }
  .rail-toggle {
    display: none;
  }

  .topbar {
    gap: 8px;
    padding-left: 12px;
    padding-right: 12px;
    min-width: 0;
  }
  .topbar .view-caption,
  .topbar .search {
    display: none;
  }
  .studio-switcher {
    min-width: 0;
    overflow: hidden;
  }
  .studio-switcher > span:not(.dot) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .topbar-actions {
    margin-left: auto;
    flex: none;
    gap: 6px;
  }
  /* the assistant keeps its glyph, loses its label */
  .btn-ai {
    font-size: 0;
    padding-left: 10px;
    padding-right: 10px;
    gap: 0;
  }
  .btn-ai svg {
    margin: 0;
  }
}

/* the member page is a phone mock beside a list. Below 900 it stacks,
   and the phone scales rather than spilling. */
@media (max-width: 900px) {
  .phone {
    max-width: 100%;
    transform-origin: top center;
  }
  .phone,
  .screen,
  .slist,
  .slist a,
  .grp {
    max-width: 100%;
    min-width: 0;
  }
  .slist a .n,
  .slist a .d {
    overflow-wrap: anywhere;
  }
}

/* ============================================================
   The opening. Signing in should feel like the X app opening:
   fast, one gesture, and over before you notice it started.
   The mark winds in, then the swirl itself opens a hole through
   the veil and the app is already behind it. Not an overlay
   fading out, an aperture.
   ============================================================ */

@property --hole {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 0%;
}

.splash {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: grid;
  place-items: center;
  pointer-events: none;
}
.splash__veil {
  position: absolute;
  inset: 0;
  /* plain white, not the app's cream. The takeover has to read as a
     different surface, otherwise it looks like a panel sliding over
     the page rather than the app not being there yet. */
  background: #fff;
  will-change: opacity;
  /* declared explicitly. A registered custom property left at its
     initial value has no "from" to interpolate and the transition
     silently jumps, which opens the aperture in one frame. */
  --hole: 0%;
}
.splash__mark {
  position: relative;
  width: 132px;
  height: 132px;
  opacity: 0;
  will-change: transform, opacity;
}
@media (max-width: 600px) {
  .splash__mark {
    width: 96px;
    height: 96px;
  }
}
.app.booting {
  transform: scale(1.045);
  transform-origin: 50% 50%;
}
.splash-done .splash {
  display: none;
}
@media (prefers-reduced-motion: reduce) {
  .splash {
    display: none;
  }
  .app.booting {
    transform: none;
  }
}

/* ============================================================
   Contrast. Measured across all 35 views at 1440, not eyeballed.

   Three tokens failed WCAG 2.2 AA for normal text on the surfaces
   they are actually painted on. Each is used hundreds of times, so
   this is one edit rather than hundreds.

     --muted  #7a7382  4.30:1 on the cream page   ->  #6f6877  5.04:1
     --green  #2e7d5b  4.36:1 inside its own pill ->  #276b4d  5.55:1
     --amber  #b77a1e  3.11:1 inside its own pill ->  #8f5e14  4.78:1

   The amber was the worst and it is the one carrying "payment
   overdue" and "expired card" at the front desk, which is the last
   text in the product that should be hard to read.
   ============================================================ */
:root {
  --muted: #6f6877;
  --green: #276b4d;
  --amber: #8f5e14;
}

/* The large meter is 64px of ring plus a 22px number. Inside a narrow
   column on a phone that pair cannot sit on one line, so let it wrap
   rather than push the column past the viewport. */
@media (max-width: 720px) {
  .arcm--lg {
    flex-wrap: wrap;
    gap: 10px;
  }
  .arcm--lg .arcm__ring {
    width: 52px;
    height: 52px;
  }
  .arcm__n {
    min-width: 0;
    white-space: normal;
  }
}

/* A hand-written `grid-template-columns: 1fr 260px` is fine at 1440 and
   blows a phone open, and it is an inline style so nothing in a
   stylesheet can beat it without !important. This is the one legitimate
   use of it: overriding an inline declaration, inside a media query, so
   desktop is untouched. Any two-up inside a page becomes one-up. */
@media (max-width: 720px) {
  .page .grid[style*="grid-template-columns"],
  .page .grid.cols-2,
  .page .grid.cols-3,
  .page .grid.cols-4 {
    /* minmax(0, 1fr), not 1fr. A grid item defaults to min-width auto,
       so a single 1fr track is still sized by its widest unbreakable
       child and a wide table drags the whole column past the screen. */
    grid-template-columns: minmax(0, 1fr) !important;
  }
  .page .grid > * {
    min-width: 0;
  }
  .page .col-2,
  .page .col-3 {
    grid-column: auto !important;
  }
}

/* A suggestion chip is nowrap by design so it never breaks mid phrase.
   On a 390px screen a long one is wider than the screen, and nowrap
   means it cannot do anything about that. Let it wrap there only. */
@media (max-width: 720px) {
  .cchip {
    white-space: normal;
    max-width: 100%;
    text-align: left;
  }
  .copilot__acts {
    justify-content: flex-start;
    min-width: 0;
  }
}

/* ============================================================
   Variants that were used but never defined.

   An undefined modifier does not error, it just silently falls back
   to the base class, so "built" and "chasing" rendered as the same
   grey tag and a missing-waiver warning rendered as a plain pill.
   Found by diffing every `x--y` class used in the HTML against every
   `.x--y` rule in the CSS, which is a check worth keeping.

   All three colour pairs measured: 4.78, 5.55 and 9.74 to 1.
   ============================================================ */
.pill--amber {
  background: var(--amber-050);
  color: var(--amber);
}
.btn--block {
  width: 100%;
  justify-content: center;
}
.tag--done {
  background: var(--green-050);
  color: var(--green);
}
.tag--do {
  background: var(--plum-050);
  color: var(--plum-700);
}
.tag--wait {
  background: var(--amber-050);
  color: var(--amber);
}

/* ============================================================
   Roles, permissions and navigation. Styles for assets/roles.js.

   The model: tier 1 network, 2 studio, 3 staff, 4 member. Going down
   is open, going up asks for a PIN. Locked items stay VISIBLE with a
   lock rather than disappearing, so a person can see the capability
   exists and knows who to ask, instead of the menu quietly changing
   shape between accounts.
   ============================================================ */

.rswrap {
  position: relative;
  flex: none;
}
.rs {
  display: flex;
  align-items: center;
  gap: 9px;
  border: 1px solid var(--line-2);
  background: var(--surface);
  border-radius: 999px;
  padding: 4px 11px 4px 4px;
  cursor: pointer;
  min-width: 0;
  transition:
    border-color 0.14s,
    box-shadow 0.14s;
}
.rs:hover {
  border-color: var(--plum);
  box-shadow: 0 1px 3px rgba(36, 28, 43, 0.08);
}
.rs__av {
  width: 28px;
  height: 28px;
  flex: none;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--plum), var(--teal));
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.rs__id {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.2;
  min-width: 0;
}
.rs__r {
  font-size: 12.5px;
  font-weight: 650;
  color: var(--ink);
  white-space: nowrap;
}
.rs__p {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}
.rs__chev {
  width: 14px;
  height: 14px;
  flex: none;
  color: var(--muted);
  transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.rswrap.open .rs__chev {
  transform: rotate(180deg);
}

.rsmenu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 330px;
  max-width: calc(100vw - 24px);
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  padding: 7px;
  z-index: 60;
  opacity: 0;
  transform: translateY(-6px) scale(0.985);
  pointer-events: none;
  transform-origin: top right;
  transition:
    opacity 0.15s ease,
    transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
.rswrap.open .rsmenu {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.rsmenu__h {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 9px 10px 5px;
}
.rsmenu__me {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 10px 10px;
  border-bottom: 1px solid var(--line);
}
.rsmenu__me b {
  display: block;
  font-size: 13.5px;
  font-weight: 650;
}
.rsmenu__me small,
.rsmenu__n small {
  display: block;
  font-size: 11px;
  color: var(--muted);
}
.rsmenu__i {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 10px;
  border-radius: var(--r-sm);
  transition: background 0.12s;
}
.rsmenu__i:hover {
  background: var(--surface-2);
}
.rsmenu__t {
  width: 19px;
  height: 19px;
  flex: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 700;
  background: var(--plum-050);
  color: var(--plum-700);
}
.rsmenu__t.t1 {
  background: var(--teal-050);
  color: var(--teal-700);
}
.rsmenu__n {
  min-width: 0;
  flex: 1;
}
.rsmenu__n b {
  font-size: 13.5px;
  font-weight: 620;
}
.rsmenu__go {
  color: var(--line-2);
  font-size: 16px;
}
.rsmenu__i:hover .rsmenu__go {
  color: var(--muted);
}
.rs__lock {
  width: 15px;
  height: 15px;
  flex: none;
  color: var(--muted);
}
.rsmenu__i.is-locked .rsmenu__n b::after {
  content: "needs a PIN";
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--amber);
  background: var(--amber-050);
  padding: 1px 6px;
  border-radius: 20px;
  margin-left: 7px;
  vertical-align: 1px;
}
.rsmenu__f {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.45;
  padding: 9px 10px 6px;
  border-top: 1px solid var(--line);
  margin-top: 4px;
}

/* the PIN dialog */
.pinback {
  position: fixed;
  inset: 0;
  z-index: 9500;
  background: rgba(36, 28, 43, 0.42);
  display: grid;
  place-items: center;
  padding: 20px;
  animation: pinfade 0.16s ease-out;
}
@keyframes pinfade {
  from {
    opacity: 0;
  }
}
.pin {
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  padding: 26px 26px 20px;
  width: 360px;
  max-width: 100%;
  text-align: center;
  animation: pinup 0.24s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes pinup {
  from {
    opacity: 0;
    transform: translateY(10px) scale(0.97);
  }
}
.pin.shake {
  animation: pinshake 0.3s;
}
@keyframes pinshake {
  20%,
  60% {
    transform: translateX(-7px);
  }
  40%,
  80% {
    transform: translateX(7px);
  }
}
.pin__ico {
  width: 44px;
  height: 44px;
  margin: 0 auto 12px;
  border-radius: 50%;
  background: var(--plum-050);
  display: grid;
  place-items: center;
  color: var(--plum);
}
.pin__ico svg {
  width: 21px;
  height: 21px;
}
.pin h2 {
  font-family: var(--font-brand);
  font-size: 23px;
  font-weight: 700;
  margin: 0 0 6px;
}
.pin p {
  color: var(--ink-2);
  font-size: 13.5px;
  margin: 0 0 16px;
  line-height: 1.5;
}
.pin__in {
  width: 150px;
  text-align: center;
  font-size: 26px;
  letter-spacing: 0.35em;
  padding: 10px 6px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  font-family: var(--font-ui);
  background: var(--surface-2);
}
.pin__in:focus {
  outline: 2px solid var(--plum);
  outline-offset: 1px;
  background: #fff;
}
.pin__err {
  color: var(--red);
  font-size: 12.5px;
  font-weight: 600;
  min-height: 19px;
  margin-top: 7px;
}
.pin__acts {
  display: flex;
  gap: 9px;
  justify-content: center;
  margin-top: 4px;
}
.pin__hint {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.45;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

/* locked and foldable navigation */
.nav-item.is-locked {
  color: var(--muted);
}
.nav-item.is-locked svg:first-child {
  opacity: 0.45;
}
.nav-item.is-locked:hover {
  background: var(--amber-050);
  color: var(--amber);
}
.nav-lock {
  margin-left: auto;
  display: flex;
  flex: none;
}
.nav-lock svg {
  width: 14px;
  height: 14px;
  opacity: 0.75;
}
.nav-section.is-foldable {
  display: flex;
  align-items: center;
  gap: 7px;
  cursor: pointer;
  user-select: none;
  border-radius: var(--r-sm);
  transition: color 0.12s;
}
.nav-section.is-foldable:hover {
  color: var(--ink-2);
}
.nav-fold {
  width: 7px;
  height: 7px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1);
  margin-left: 1px;
}
.nav-section.folded .nav-fold {
  transform: rotate(-45deg);
}
.nav-item.nav-hidden {
  display: none;
}
.app.rail .nav-section.is-foldable,
.app.rail .nav-fold {
  display: none;
}
/* collapsed to a rail, a folded group would hide items with no way back */
.app.rail .nav-item.nav-hidden {
  display: flex;
}

/* ============================================================
   The hotkey bar. Was a static preview pill. Now a small permanent
   control that grows on hover, holds up to six pinned views, answers
   to the number keys, and can be switched off.
   ============================================================ */

.hotbar {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  z-index: 800;
  display: flex;
  align-items: center;
  gap: 6px;
  background: rgba(30, 22, 38, 0.93);
  backdrop-filter: saturate(1.4) blur(9px);
  -webkit-backdrop-filter: saturate(1.4) blur(9px);
  border: 1px solid rgba(255, 255, 255, 0.11);
  border-radius: 999px;
  padding: 5px;
  box-shadow: 0 8px 30px rgba(20, 12, 28, 0.3);
  max-width: calc(100vw - 24px);
  transition:
    padding 0.2s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.2s;
}
.hotbar.gone {
  display: none;
}
.hotbar.flash {
  box-shadow:
    0 8px 30px rgba(20, 12, 28, 0.3),
    0 0 0 3px rgba(205, 106, 23, 0.5);
}
.hotbar__grip {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 4px 5px 11px;
  color: rgba(255, 255, 255, 0.62);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}
.hotbar__grip svg {
  width: 14px;
  height: 14px;
  opacity: 0.75;
}
.hotbar__slots {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.hotbar__slots::-webkit-scrollbar {
  display: none;
}
.hot {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 11px 7px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 0;
  color: rgba(255, 255, 255, 0.9);
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 550;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background 0.14s,
    transform 0.14s;
}
.hot:hover {
  background: rgba(255, 255, 255, 0.17);
  transform: translateY(-1px);
}
.hot kbd {
  font-family: var(--font-ui);
  font-size: 10.5px;
  font-weight: 700;
  min-width: 17px;
  height: 17px;
  display: grid;
  place-items: center;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
}
/* the labels only appear once you are interested in the bar */
.hot > span {
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  transition:
    max-width 0.22s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.16s;
}
.hotbar:hover .hot > span,
.hotbar:focus-within .hot > span {
  max-width: 150px;
  opacity: 1;
}
.hot__x {
  border: 0;
  background: none;
  color: rgba(255, 255, 255, 0.45);
  font-size: 13px;
  line-height: 1;
  padding: 0 0 0 2px;
  cursor: pointer;
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  transition:
    max-width 0.22s,
    opacity 0.16s;
}
.hotbar:hover .hot__x {
  max-width: 14px;
  opacity: 1;
}
.hot__x:hover {
  color: #fff;
}
.hot--add {
  background: none;
  border: 1px dashed rgba(255, 255, 255, 0.24);
  color: rgba(255, 255, 255, 0.62);
}
.hotbar__off {
  border: 0;
  background: none;
  color: rgba(255, 255, 255, 0.4);
  cursor: pointer;
  padding: 6px 9px 6px 4px;
  font-size: 16px;
  line-height: 1;
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  transition:
    max-width 0.22s,
    opacity 0.16s;
}
.hotbar:hover .hotbar__off {
  max-width: 30px;
  opacity: 1;
}
.hotbar__off:hover {
  color: #fff;
}
.hotpick {
  position: absolute;
  bottom: calc(100% + 9px);
  left: 50%;
  transform: translateX(-50%);
  width: 250px;
  max-width: calc(100vw - 24px);
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  padding: 8px;
  animation: pinup 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.hotpick__h {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 6px 8px 7px;
}
.hotpick__l {
  display: flex;
  flex-direction: column;
  max-height: 290px;
  overflow-y: auto;
}
.hotpick__l button {
  text-align: left;
  border: 0;
  background: none;
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink-2);
  padding: 8px 9px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.hotpick__l button:hover {
  background: var(--plum-050);
  color: var(--plum);
}

@media (max-width: 720px) {
  .rs__id {
    display: none;
  }
  .rs {
    padding: 4px;
  }
  .hotbar__grip span {
    display: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .hot > span,
  .hot__x,
  .hotbar__off {
    transition: none;
  }
}

/* ============================================================
   The action layer. Styles for assets/actions.js.
   Nothing in the product is a dead click, so every button opens
   one of these: a drawer for inspecting, a modal for deciding.
   ============================================================ */

.pnback {
  position: fixed;
  inset: 0;
  z-index: 9200;
  background: rgba(36, 28, 43, 0);
  transition: background 0.22s ease;
  display: flex;
  justify-content: flex-end;
}
.pnback.on {
  background: rgba(36, 28, 43, 0.38);
}
.pn {
  background: var(--surface);
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-lg);
  max-height: 100%;
}
.pn--drawer {
  width: 520px;
  max-width: 100%;
  height: 100%;
  transform: translateX(100%);
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.pnback.on .pn--drawer {
  transform: none;
}
.pn--modal {
  width: 480px;
  max-width: calc(100% - 32px);
  margin: auto;
  border-radius: var(--r-lg);
  transform: translateY(14px) scale(0.98);
  opacity: 0;
  transition:
    transform 0.26s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.18s ease;
}
.pnback:has(.pn--modal) {
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.pnback.on .pn--modal {
  transform: none;
  opacity: 1;
}
.pn__head {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 20px 22px 16px;
  border-bottom: 1px solid var(--line);
  flex: none;
}
.pn__t {
  font-family: var(--font-brand);
  font-size: 20px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
  flex: 1;
  min-width: 0;
}
.pn__s {
  display: block;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--muted);
  margin-top: 3px;
  letter-spacing: 0;
}
.pn__x {
  border: 0;
  background: var(--surface-2);
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 6px;
  font-size: 20px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
}
.pn__x:hover {
  background: var(--line);
  color: var(--ink);
}
.pn__body {
  padding: 18px 22px 22px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
.pn__f {
  margin-bottom: 16px;
  min-width: 0;
}
.pn__f > label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.pn__v {
  font-size: 13px;
  color: var(--ink);
  min-width: 0;
}
.pn__h {
  font-size: 12px;
  color: var(--muted);
  margin-top: 5px;
  line-height: 1.45;
}
.pn__sel {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.pn__opt {
  border: 1px solid var(--line-2);
  background: var(--surface);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-2);
  padding: 7px 12px;
  border-radius: 999px;
  cursor: pointer;
  transition:
    background 0.12s,
    border-color 0.12s,
    color 0.12s;
}
.pn__opt:hover {
  border-color: var(--plum);
}
.pn__opt.on {
  background: var(--plum);
  border-color: var(--plum);
  color: #fff;
}
.pn__in {
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  padding: 9px 11px;
  font-size: 13px;
  min-height: 38px;
  color: var(--ink);
}
.pn__ph {
  color: var(--muted);
}
.pn__note {
  background: var(--plum-050);
  border-left: 3px solid var(--plum);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  padding: 11px 13px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0 0 18px;
}
.pn__acts {
  display: flex;
  gap: 9px;
  justify-content: flex-end;
  border-top: 1px solid var(--line);
  margin-top: 20px;
  padding-top: 18px;
}
.btn--danger {
  background: var(--red);
  color: #fff;
  border-color: var(--red);
}
@media (max-width: 560px) {
  .pn--drawer {
    width: 100%;
  }
}
@media (prefers-reduced-motion: reduce) {
  .pn--drawer,
  .pn--modal,
  .pnback {
    transition: none;
  }
}

/* ============================================================
   Bugs found in real use, 2026-08-06.
   ============================================================ */

/* 1. Collapsed to a rail, 24 icons overflowed the viewport and the
      Collapse control sat below the fold, so there was no way back. */
.rail-toggle {
  position: sticky;
  bottom: 0;
  z-index: 2;
  background: linear-gradient(180deg, rgba(250, 246, 239, 0), #faf6ef 34%);
  padding-top: 16px;
  margin-top: auto;
}
.sidebar__foot {
  position: sticky;
  bottom: 0;
  background: #faf6ef;
  z-index: 2;
}

/* 2. The topbar ran off the right edge: the search took every spare
      pixel and the actions had nothing left to shrink into. */
.topbar {
  min-width: 0;
  gap: 12px;
}
.topbar .search {
  min-width: 0;
  flex: 1 1 auto;
}
.topbar-actions {
  flex: none;
  margin-left: auto;
  min-width: 0;
}
.view-caption {
  flex: none;
  white-space: nowrap;
}
@media (max-width: 1240px) {
  .view-caption {
    display: none;
  }
}

/* 3. A search over the navigation. 24 items is past the point where
      scanning beats typing. */
.nav-search {
  position: relative;
  margin: 0 0 8px;
  flex: none;
}
.nav-search input {
  width: 100%;
  border: 1px solid var(--line-2);
  background: var(--surface);
  border-radius: var(--r-sm);
  padding: 8px 10px 8px 30px;
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink);
}
.nav-search input::placeholder {
  color: var(--muted);
}
.nav-search input:focus {
  outline: 2px solid var(--plum);
  outline-offset: -1px;
  background: #fff;
}
.nav-search svg {
  position: absolute;
  left: 9px;
  top: 50%;
  transform: translateY(-50%);
  width: 14px;
  height: 14px;
  color: var(--muted);
  pointer-events: none;
}
.app.rail .nav-search {
  display: none;
}
.nav-item.nav-nomatch,
.nav-section.nav-nomatch {
  display: none;
}

/* 4. The account, bottom left, where the field puts it. */
.acct {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: 0;
  background: none;
  padding: 10px 8px;
  border-radius: var(--r-sm);
  cursor: pointer;
  text-align: left;
  min-width: 0;
  transition: background 0.12s;
}
.acct:hover {
  background: var(--surface-2);
}
.acct__av {
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--plum), var(--teal));
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 700;
}
.acct__id {
  min-width: 0;
  flex: 1;
  line-height: 1.25;
}
.acct__n {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.acct__r {
  display: block;
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.acct__c {
  flex: none;
  color: var(--muted);
  font-size: 13px;
}
.app.rail .acct__id,
.app.rail .acct__c {
  display: none;
}
.app.rail .acct {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}

/* 5. A count out of a small whole number is not a capacity meter, and
      an arc reads as one. 7 studios of 8 is a list, so it is drawn as
      8 pips you can actually count, with the exception named. */
.pips {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 10px 0 0;
  flex-wrap: wrap;
}
.pip {
  width: 26px;
  height: 6px;
  border-radius: 6px;
  background: var(--green);
}
.pip--no {
  background: var(--line-2);
}
.pip--warn {
  background: var(--amber);
}
.ratio {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.ratio__n {
  font-family: var(--font-brand);
  font-size: var(--fs-focal);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.01em;
}
.ratio__of {
  font-size: 16px;
  color: var(--muted);
  font-weight: 500;
}

/* ============================================================================
   ORG TREE, hq.html data-page="people"
   ----------------------------------------------------------------------------
   A reporting hierarchy drawn in plain nested <ul>, no library. The connectors
   are borders on ::before and ::after, so it stays a real list for a screen
   reader and it prints.

   Two kinds of branch:
     ul.orgtree__branch  children fan out sideways, used for HQ to studios to
                         owner. Wide, so the host container scrolls.
     ul.orgtree__staff   children stack downward off a left spine, used for the
                         staff under one owner. Keeps the whole tree to nine
                         columns instead of twenty-eight.

   The host is a .table-wrap, which already scrolls on x. Below 720px the whole
   thing flattens into a plain indented list.

   Every selector here is scoped under .orgtree. Nothing existing is redefined.
   ========================================================================== */

.orgtree {
  width: max-content;
  min-width: 100%;
  margin: 0;
  padding: 22px 20px 26px;
  list-style: none;
  text-align: center;
  --orgtree-line: var(--line-2);
  --orgtree-drop: 22px;
}
.orgtree ul {
  list-style: none;
}

/* ---- the sideways branch ---------------------------------------------- */

.orgtree__branch {
  display: flex;
  justify-content: center;
  margin: 0;
  padding: var(--orgtree-drop) 0 0;
  position: relative;
}
/* the line dropping out of the parent node into this branch */
.orgtree li > .orgtree__branch::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 0;
  height: var(--orgtree-drop);
  border-left: 1px solid var(--orgtree-line);
}
.orgtree__branch > li {
  position: relative;
  padding: var(--orgtree-drop) 9px 0;
  text-align: center;
}
/* the two halves of the horizontal rail above each child */
.orgtree__branch > li::before,
.orgtree__branch > li::after {
  content: "";
  position: absolute;
  top: 0;
  width: 50%;
  height: var(--orgtree-drop);
  border-top: 1px solid var(--orgtree-line);
}
.orgtree__branch > li::before {
  right: 50%;
}
.orgtree__branch > li::after {
  left: 50%;
  border-left: 1px solid var(--orgtree-line);
}
/* an only child needs no rail, just the drop that is already drawn */
.orgtree__branch > li:only-child::before,
.orgtree__branch > li:only-child::after {
  display: none;
}
.orgtree__branch > li:only-child {
  padding-top: 0;
}
/* trim the rail at the two ends and round the corners */
.orgtree__branch > li:first-child::before,
.orgtree__branch > li:last-child::after {
  border: 0;
}
.orgtree__branch > li:last-child::before {
  border-right: 1px solid var(--orgtree-line);
  border-radius: 0 6px 0 0;
}
.orgtree__branch > li:first-child::after {
  border-radius: 6px 0 0 0;
}

/* ---- the stacked staff spine ------------------------------------------ */

.orgtree__staff {
  margin: 0 0 0 26px;
  padding: 0;
  text-align: left;
}
.orgtree__staff > li {
  position: relative;
  padding: 12px 0 0 22px;
}
.orgtree__staff > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  border-left: 1px solid var(--orgtree-line);
}
/* 40px is the measured distance from a staff li's top to the middle of the
   node inside it, so the tick meets the card rather than its corner. */
.orgtree__staff > li:last-child::before {
  bottom: auto;
  height: 40px;
}
.orgtree__staff > li::after {
  content: "";
  position: absolute;
  left: 0;
  top: 40px;
  width: 22px;
  height: 0;
  border-top: 1px solid var(--orgtree-line);
}

/* ---- the node --------------------------------------------------------- */

/* Avatar on the left spanning every text row, so a node stays about 46px tall
   and the staff spine can meet it at a predictable height. */
.orgtree__n {
  display: inline-grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: 9px;
  row-gap: 1px;
  min-width: 172px;
  max-width: 212px;
  padding: 9px 12px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  text-align: left;
}
.orgtree__n > .avatar {
  grid-column: 1;
  grid-row: 1 / -1;
}
.orgtree__n > .orgtree__nm,
.orgtree__n > .orgtree__rl,
.orgtree__n > .orgtree__ct,
.orgtree__n > .pill {
  grid-column: 2;
}
.orgtree__n > .pill {
  justify-self: start;
  margin-top: 5px;
}
.orgtree__nm {
  font-size: 13px;
  font-weight: 650;
  color: var(--ink);
  line-height: 1.25;
}
.orgtree__rl {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.35;
}
.orgtree__ct {
  margin-top: 2px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--teal);
}
.orgtree__n--root {
  border-color: var(--plum);
  background: var(--plum-050);
}
.orgtree__n--root .orgtree__ct {
  color: var(--plum);
}
.orgtree__n--studio {
  min-width: 184px;
  border-style: dashed;
  background: var(--surface-2);
}
.orgtree__n--studio .orgtree__nm {
  font-size: 12.5px;
}
.orgtree__n--leaf {
  min-width: 162px;
  padding: 8px 11px;
  box-shadow: none;
}
.orgtree__n--off {
  border-color: #e6d3d3;
  background: var(--red-050);
}
.orgtree__n--off .orgtree__nm,
.orgtree__n--off .orgtree__ct {
  color: var(--red);
}

/* ---- phone, flatten to a plain indented list -------------------------- */

@media (max-width: 720px) {
  .orgtree {
    width: auto;
    min-width: 0;
    padding: 14px 12px 18px;
    text-align: left;
  }
  .orgtree__branch,
  .orgtree__staff {
    display: block;
    margin: 0 0 0 12px;
    padding: 0 0 0 12px;
    border-left: 1px solid var(--orgtree-line);
    text-align: left;
  }
  .orgtree li > .orgtree__branch::before {
    display: none;
  }
  .orgtree__branch > li,
  .orgtree__staff > li {
    display: block;
    padding: 10px 0 0;
    text-align: left;
  }
  .orgtree__branch > li::before,
  .orgtree__branch > li::after,
  .orgtree__staff > li::before,
  .orgtree__staff > li::after {
    display: none;
  }
  .orgtree__n,
  .orgtree__n--studio,
  .orgtree__n--leaf {
    display: flex;
    min-width: 0;
    max-width: none;
    width: 100%;
  }
}

/* ============================================================================
   2026-08-06 defect pass. Four fixes, appended, nothing above redefined.

   B3  an icon beside a label
   B2  a countable set of seats
   B1  a control that can be hidden has a visible way back
   M1  a settings gear on every section of the left rail
   ============================================================================ */

/* B3. The apparatus icon on the video library sat at the top of its line
   and pushed "Reformer" onto a second row.

   The cause was not a margin. `.tag` is inline-flex with no align-items,
   so a child with a definite height is laid out at flex-start, which puts
   a 12px icon at the top of a 17px line box, and the label, being an
   anonymous flex item, was free to shrink and wrap inside a narrow column.
   Nudging a margin would have moved the icon and left the wrap.

   So it is stated as the general rule, once, for every icon-beside-label
   pair in the product rather than for the one that was reported: the icon
   is a fixed box centred on the label, the label does not wrap, and the
   two are separated by a gap rather than by a whitespace text node that
   flex layout collapses away. `:has(> svg)` keeps it off the tags and
   pills that carry no icon, which must not gain a gap. */
:is(
  .tag,
  .pill,
  .btn,
  .link,
  .chip,
  .card__title,
  .metric__label,
  .classcell
):has(> svg) {
  align-items: center;
  white-space: nowrap;
}
.tag:has(> svg) {
  gap: 5px;
}
:is(.tag, .pill, .btn, .link, .chip, .card__title, .metric__label, .classcell)
  > svg {
  flex: none;
  align-self: center;
}

/* B2. A countable set of named things, not a percentage.

   Two columns qualify and both had been drawn as a continuum. Seats in a
   cohort, where 14 of 16 is chairs in a room, and Acknowledged in the
   standards and announcement tables, where 5 of 8 is five named studios.
   An arc and a bar both say "some percentage of something continuous",
   which is why the same idea kept reading wrong in three components.
   `.pips` already exists for exactly this, one mark per unit, and is
   what 7 of 8 studios is drawn with on the HQ overview.

   What stays an arc: capacity against a physical limit. A class filling
   toward 12 reformers is rule 4 of the build contract and has never been
   objected to. What stays a bar: a completion percentage, tuition
   collected, course progress, compliance percent.

   The ratio leads and the marks follow, so the number sits at the same x
   on every row and the column can be read down. The number is never
   dropped, because eight marks only say eight if you count them. Filled
   is plum, the colour training already owns; empty is the hairline.

   Past 24 the marks stop being countable at a glance and stop fitting a
   table cell, so polish.py writes the ratio alone and draws none. That
   threshold lives in polish.py as PIP_MAX. Nothing in the product is
   near it, the largest set is 18. */
.pips--count {
  margin: 0;
  gap: 3px;
  flex-wrap: nowrap;
}
.pips--count .pip {
  width: 5px;
  height: 14px;
  border-radius: 2px;
  background: var(--plum);
}
.pips--count .pip--no {
  background: var(--line-2);
}
.pips__n {
  font-size: 12px;
  font-weight: 650;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  margin-right: 7px;
  min-width: 46px;
}
/* the cohort card carries its own "14 / 16 seats" line, so the marks
   there are the whole story and can be read from further away */
.pips--lg {
  gap: 4px;
}
.pips--lg .pip {
  width: 9px;
  height: 20px;
  border-radius: 6px;
}

/* B1. The jump bar could be dismissed with no way back.

   Second time a control has been hidden with no route to it, after the
   sidebar collapse. The rule now: nothing hides completely. The bar
   docks to a handle at the same edge it left, the handle is permanent,
   and J toggles it from anywhere. Built in assets/roles.js. */
.hotdock {
  position: fixed;
  left: 50%;
  bottom: 0;
  z-index: 799;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 14px 7px;
  border: 1px solid rgba(255, 255, 255, 0.11);
  border-bottom: 0;
  border-radius: 10px 10px 0 0;
  background: rgba(30, 22, 38, 0.93);
  backdrop-filter: saturate(1.4) blur(9px);
  -webkit-backdrop-filter: saturate(1.4) blur(9px);
  color: rgba(255, 255, 255, 0.72);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transform: translateX(-50%) translateY(110%);
  transition:
    transform 0.24s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.16s,
    color 0.14s;
}
.hotdock.on {
  opacity: 1;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
.hotdock:hover {
  color: #fff;
}
.hotdock svg {
  width: 13px;
  height: 13px;
  flex: none;
  opacity: 0.8;
}
.hotdock kbd {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  min-width: 15px;
  height: 15px;
  display: grid;
  place-items: center;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
}

/* M1. A settings gear on every section of the left rail.

   Out of flow, not in it. In flow it costs 28px of the row, which is
   exactly what "Teacher Training" and "Trainees I mentor" had spare,
   and both labels broke onto a second line the moment the gear
   appeared. Same defect as B3, introduced by the fix for M1, caught by
   measuring every label rather than by looking at the screen.

   So the gear is absolute, costs nothing, and the unread count slides
   left out of its way with a transform, which is also free. Nothing
   reflows, nothing is hidden, no number is traded for an affordance.

   Visible on hover, on keyboard focus, and always on the section you
   are standing in. Hidden when the rail is collapsed, where there is
   no room and no label to attach it to. */
.nav-cog {
  position: absolute;
  right: 8px;
  top: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: none;
  color: inherit;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-50%);
  transition:
    opacity 0.12s,
    background 0.12s;
}
.nav-cog svg {
  width: 14px;
  height: 14px;
  opacity: 0.75;
}
/* not in the rail. There the count is already an absolutely positioned
   dot in the icon's corner and there is no gear to make room for, so
   sliding it would just push the dot off the icon. */
.app:not(.rail) .nav-item:hover .count,
.app:not(.rail) .nav-item:focus-within .count,
.app:not(.rail) .nav-item.active .count {
  transform: translateX(-26px);
  transition: transform 0.14s cubic-bezier(0.22, 1, 0.36, 1);
}
/* a rail label that wraps is a rail label that is wrong. Nothing needs
   this today now that the gear is out of flow, it is here so a longer
   section name added later fails visibly rather than silently. */
.nav-item > span:not(.count) {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.nav-item:hover .nav-cog,
.nav-item:focus-within .nav-cog,
.nav-item.active .nav-cog {
  opacity: 1;
  pointer-events: auto;
}
.nav-cog:hover {
  background: rgba(91, 61, 117, 0.14);
}
.nav-cog:hover svg {
  opacity: 1;
}
.nav-cog:focus-visible {
  opacity: 1;
  pointer-events: auto;
  outline: 2px solid var(--plum);
  outline-offset: 1px;
}
.app.rail .nav-cog {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .hotdock,
  .nav-cog {
    transition: none;
  }
}
