/* ============================================================================
   Tendd - the reviewer's chrome around a coloured screen.

   THIS FILE SHIPS WITH NOTHING. It is the frame a reviewer reads the product
   through: the roadmap drawer, the toggle that opens it, and the padded stage
   the screen stands in. Delete it and the product is unchanged; delete
   design/system/ and there is no product.

   IT EXISTS BECAUSE kit.css IS BEING DELETED, and this material was inside it.
   Ten classes on all 28 coloured screens (`.layout`, `.stage`, `.stage-app`,
   `.sidebar` and its five parts, `.nav-toggle`, `.nav-brand`) were declared in
   `design/kit/kit.css` and nowhere else. The renaming map of step 2 sent them
   "out of the system, to `_page.css`", and that answer is right about the first
   half and wrong about the second: `design/kit/_page.css` is the STAND's
   stylesheet and a product screen does not load it. So the chrome needed a home
   of its own, next to the script that draws it, and this is it.

   WHY NOT design/system/. Because that folder is liftable whole into a build,
   and a build has no roadmap drawer. A review affordance inside the shipped
   package is the same defect as a product class inside the stand, read from the
   other end.

   VALUES MOVED BYTE FOR BYTE out of kit.css, including the `--c-` chrome
   palette, which was declared in the same `:root` as the product's tokens and
   consumed only here. Two things did NOT come with them, and both are named
   below where they would have been.

   Its sibling in the grey half of the project is `wireframes/_wf.css`, which
   does the same job for the wireframes. Loaded by every page in `design/`
   alongside `system/index.css`.
   ============================================================================ */

:root {
  /* The review chrome's own palette, sage and cream, from the phase site. It is
     deliberately NOT the product's palette: a reviewer has to be able to tell at
     a glance which pixels are Tendd and which are the frame around it.

     `--c-bg` was declared beside these and consumed nowhere; it was dropped at
     stage 07 step 6 and is not resurrected here.

     Two were darkened at stage 07 step 7 after the audit measured them.
     `--c-text-muted` was #9b958e, 2.96:1 on white, and it carries the state
     links and the panel label; `--c-accent` was #5c7a6e, 4.22:1 on its own
     tint, and it marks the CURRENT page, so the one row that must be readable
     was the one that failed. Review chrome, but a reviewer reads it on every
     screen. */
  --c-surface: #ffffff;
  --c-border: #e8e4dc;
  --c-border-light: #f0ede6;
  --c-text: #2a2724;            /* 14.85:1 on --c-surface */
  --c-text-secondary: #68625d;  /*  6.01:1, darkened from #6b6560 on 2026-08-23 */
  --c-text-muted: #6f6a63;      /*  5.36:1 */
  --c-accent: #4e6a5c;          /*  5.93:1 on --c-surface, 5.32:1 on --c-accent-light */
  --c-accent-light: #eef4f1;
  --c-control-edge: #8f887e;    /*  3.51:1 on --c-surface. See the dark half for why */
  --c-radius-sm: 4px;

  /* THE ONLY GEOMETRY IN THE CHROME'S PALETTE, and it earns the name on
     2026-08-12 because two rules now have to agree about it. The toggle is a
     strip in normal flow above the screen, so its height is exactly the amount
     the shell has to give back at a desktop width, and a shell one strip too tall
     scrolls the review page by that strip. One owner, two readers. */
  --c-toggle-h: 40px;
}

/* THE CHROME HAS A DARK PAIR, added 2026-08-12 by the dark stress test, and the
   finding that produced it is a NEIGHBOURHOOD one: nothing in this file was
   broken and nothing in the system was broken, and together they were wrong.

   The panel's ground is chrome and fixed; the panel's ink is not all its own.
   `.sidebar` sets `background: var(--c-surface)` and inherits `color` from
   `body`, which reads the product's `--text-primary`. In the dark theme that
   resolves to #eef3f4 on a #ffffff panel: 1.09:1. Every row inside happens to
   declare a --c- colour of its own and so stayed readable, which is why the
   defect measured rather than showed, and it is one added row away from showing.

   THE VALUES ARE design/kit/_page.css's --kn- SET, name for name. That file is
   the same sage and cream chrome doing the same job on the stand, and it has
   carried a dark pair since step 4. Two reviewer panels disagreeing about their
   own colour would be a new drift invented to cure an old one. Contrast measured
   on --c-surface dark; the light figures stand next to the light values above,
   so a pair is read on one line. */
[data-theme="dark"] {
  --c-surface: #171d1f;
  --c-border: #2b3538;
  --c-border-light: #222b2e;
  --c-text: #e6edee;            /* 14.38:1 on --c-surface */
  --c-text-secondary: #b1bdc0;  /*  8.86:1 */
  --c-text-muted: #94a1a4;      /*  6.41:1 */
  --c-accent: #8fc2ac;          /*  8.51:1 on --c-surface, 7.46:1 on --c-accent-light */
  --c-accent-light: #1b2a25;
  --c-control-edge: #6b7578;    /*  3.60:1 on --c-surface */
}

/* --c-control-edge IS ITS OWN NAME, and one control needs it. --c-border draws
   the panel's outline and the rules between its parts, where it is decoration:
   1.27:1 light, 1.35:1 dark, and both are correct for what they do. The theme
   switch's unpressed button is a different job. It is a CONTROL, its edge is the
   only thing that says where it starts, and 1.4.11 asks 3:1 of exactly that.
   Reusing --c-border would have put the switch at 1.35:1 on the dark panel and
   1.27:1 on the light one, which is the same mistake the product's own palette
   made and corrected on 2026-08-11 when --edge was split off the hairline. Two
   jobs, two names, and the pair is written at the moment the name is declared. */

/* NOT CARRIED, ONE: the rule that hid the wireframe review annotations,
   `.zlabel, .zaction, .pane-note, .gc-tag { display: none !important }`. It was
   written when the coloured screens were copied from the grey ones, to suppress
   the annotation layer that came across with the markup. Counted before it was
   dropped: those four classes occur ZERO times across all 28 coloured screens,
   and neither `design/_nav.js` nor the root `/_nav.js` injects one. The
   annotations were removed from the markup itself at stage 07 and the rule has
   been guarding an empty room ever since. It was also the file's only
   `!important`. */

/* ---------- the roadmap drawer -------------------------------------------
   visibility, not just transform. Off-canvas by transform alone leaves sixteen
   chrome links in the tab order and in the accessibility tree, so on a phone a
   keyboard user tabs through an invisible panel before reaching the product.
   visibility:hidden takes them out and still animates, because visibility is a
   transitionable property when it is paired with a duration. */
.sidebar {
  position: fixed; top: 0; left: 0; bottom: 0; width: 220px;
  background: var(--c-surface); border-right: 1px solid var(--c-border);
  z-index: 200; transform: translateX(-100%); visibility: hidden;
  transition: transform 0.22s ease, visibility 0.22s;
  overflow-y: auto; padding-bottom: 32px;
}
.sidebar.open { transform: translateX(0); visibility: visible; }
.sidebar-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.25); z-index: 150; }
.sidebar-overlay.open { display: block; }
.sidebar-header { display: flex; align-items: center; justify-content: space-between; padding: 18px 16px 14px; border-bottom: 1px solid var(--c-border-light); }
.nav-brand { font-weight: 600; font-size: 13.5px; color: var(--c-text); letter-spacing: -0.01em; }
.sidebar-close { background: none; border: none; font-size: 18px; line-height: 1; color: var(--c-text-muted); cursor: pointer; padding: 4px 6px; border-radius: var(--c-radius-sm); }

/* Review chrome, not the product, and it is not allowed to sit on top of the
   product. Floating it anywhere covers something: at the top it covered the
   wordmark, above the tab bar it covered the removal note. The grey wireframes
   already solved this with a strip in normal flow above the screen, so this is
   the same answer rather than a third guess.

   IT USED TO BE HIDDEN FROM 840 AND IT IS NOW SHOWN AT EVERY WIDTH. See the
   overlay decision below. */
.nav-toggle {
  position: static; display: flex; align-items: center; justify-content: flex-start;
  gap: 10px;
  width: 100%; height: var(--c-toggle-h); padding: 0 14px; z-index: 100;
  background: var(--c-surface); border: 0; border-bottom: 1px solid var(--c-border);
  border-radius: 0; box-shadow: none; cursor: pointer;
  color: var(--c-text-secondary); font-size: 13px; text-align: left;
}

/* THE LABEL IS IN CSS AND NOT IN THE MARKUP, and both halves of that are on
   purpose. It is added on 2026-08-12 because the panel stopped being docked: the
   button used to be a phone-only affordance and is now the ONLY way to the screen
   list at any width, and a bare hamburger at the top of a desktop window is a
   thing a reviewer has to guess at. The rule that already declares this element
   `font-size: 13px` and `text-align: left` was written for a label it never had.

   In CSS because the button's markup is written out in all 28 coloured screens
   rather than injected, so a word in the markup is 28 edits to product files for
   a piece of review chrome. Generated content is chrome-only by construction and
   comes off in one line if the dock ever comes back.

   It does not touch the accessible name. The button carries
   `aria-label="Open navigation"`, which overrides its contents, so a screen
   reader hears one label rather than two. */
.nav-toggle::after { content: "All screens"; }

.sidebar-nav { padding: 12px 10px 0; }

/* THE THEME SWITCH. Drawn by design/_nav.js at the top of the panel, so a screen
   added tomorrow gets it without being told. It is chrome and reads --c- values
   only: a control for looking at the product is not part of the product, and a
   switch painted in the theme it is switching cannot be told apart from the thing
   it switches. The pressed state repaints, it does not add a border, so nothing
   under it moves by a pixel when the choice changes. */
.scr-theme { display: flex; gap: 6px; margin: 0 0 10px; }
.scr-theme button {
  flex: 1; min-height: 32px; padding: 0; border: 1px solid var(--c-control-edge);
  border-radius: var(--c-radius-sm); background: none; font: inherit; font-size: 12px;
  color: var(--c-text-secondary); cursor: pointer;
}
.scr-theme button:hover { background: var(--c-border-light); color: var(--c-text); }
.scr-theme button[aria-pressed="true"] { background: var(--c-accent-light); border-color: var(--c-accent); color: var(--c-accent); font-weight: 600; }
.scr-theme button:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }

.scr-label { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--c-text-muted); padding: 10px 8px 5px; }
.scr-label.active { color: var(--c-accent); }
.sidebar-nav .scr-link { display: block; text-decoration: none; color: var(--c-text-secondary); font-size: 13px; padding: 6px 10px; border-radius: var(--c-radius-sm); margin-bottom: 1px; transition: background 0.15s, color 0.15s; }
.sidebar-nav .scr-link:hover { color: var(--c-text); background: var(--c-border-light); }
.scr-current { display: block; font-size: 13px; font-weight: 600; color: var(--c-accent); padding: 6px 10px; border-radius: var(--c-radius-sm); background: var(--c-accent-light); margin-bottom: 1px; }
.sidebar-nav .scr-back { display: block; text-decoration: none; color: var(--c-accent); font-size: 13px; font-weight: 600; padding: 6px 10px; margin-bottom: 6px; border-radius: var(--c-radius-sm); }
.sidebar-nav .scr-back:hover { background: var(--c-accent-light); }
.sidebar-nav .scr-back.current { color: var(--c-text-muted); }
.scr-states { list-style: none; margin: 0 0 8px; padding: 0 0 0 18px; }
.scr-states li { margin: 0; }
.scr-states a { display: block; text-decoration: none; color: var(--c-text-muted); font-size: 12px; padding: 3px 10px; border-radius: var(--c-radius-sm); }
.scr-states a:hover { color: var(--c-text); background: var(--c-border-light); }
.scr-states a.current { color: var(--c-accent); font-weight: 600; background: var(--c-accent-light); }

/* ============================================================================
   THE PANEL IS AN OVERLAY AT EVERY WIDTH, 2026-08-12, AND THE BLOCK THAT USED TO
   STAND HERE IS DELETED RATHER THAN NARROWED.

   What was here: `@media (min-width: 840px)` pinned the drawer open, hid the
   toggle, hid the overlay, gave `body` 220px of left padding and pushed the
   product's fixed tab bar by the same 220. Six declarations, one idea: past 840
   the reviewer gets a permanent screen list and the product gets whatever is
   left.

   WHY IT HAD TO GO. `base.css` declares the product's container on `body` and
   `.stage` below declares a nearer one, and a container query reads the CONTENT
   box. 220px of body padding therefore did not just move the panel, it told the
   product it was 220px narrower than the window. Walked at fourteen widths on
   Home before the change, and the shell's form is not monotonic in window width:

     window   360  700  760  800 | 840  860  900  960 | 980  1024  1280  1440
     shell    mob  mob  GRID GRID| mob  mob  mob  mob | GRID GRID  GRID  GRID

   Between 840 and 980 every coloured screen rendered its MOBILE layout inside a
   desktop window: at 900 the product measured 680. Both accepted viewports miss
   it, 360 and 1280 sitting either side of the band, which is the exact shape
   `CLAUDE.md` names when it asks for acceptance at BOTH ends of the range. A
   screen reviewed in that band was not showing what it ships.

   WHY THE OVERLAY AND NOT A WIDER DOCK. Moving the dock to 980 repairs the 760
   boundary and leaves the 900 one broken by the same 220px, because a fixed dock
   can only ever be clear of one step. The overlay is the only form where the
   container equals the window at EVERY width, so both points fire where they say
   they do. (Written when the product had three steps and 1340 was one of them.
   Stage 10 removed that one: the count it switched is now computed from a floor,
   and the argument above holds unchanged for the two that are left.) Founder's
   call, and the cost was named before it was taken: the screen list is no longer
   permanently on screen and opens from the toggle. The mechanism is not new, it
   is the one that has run below 840 since the chrome was written.

   The `!important` that stood on the overlay at stage 07 is still not carried:
   it was there to beat `.sidebar-overlay.open`, and with the block gone there is
   nothing left to beat.

   ONE CORRECTION THE CHROME OWES ITSELF, and it replaces the tab bar offset that
   used to be the last line of the deleted block. The toggle is a 40px strip in
   normal flow ABOVE the screen, and past a 760px container the shell is exactly
   `100dvh` tall, so the review page stood one strip taller than the window and
   scrolled by 40px at every desktop width. Measured before, and it was already
   true in the 760 to 840 band, where the toggle showed and the dock had not yet
   started: `SCROLLS +40` at 760 and at 800.

   It is stated HERE, on the chrome's own selector, and never in `design/system/`:
   a build has no toggle and must not carry a subtraction for one. `.stage-app
   .app` is 0-2-0 against the shell's own 0-1-0, and a container query adds no
   specificity, so this wins without an `!important`. Inside a container query of
   its own because at the mobile width the shell is a `min-height` column and a
   height here would cut the page off. Both units, in the shell's own order, so
   the fallback behaves the same way it does in the product.

   AND IT TAKES FOUR DECLARATIONS RATHER THAN TWO, WHICH IS THE FINDING. The
   first try set `height` alone and moved nothing: the page still scrolled 40px
   with the rule matching and winning. The shell's MOBILE rule sets `min-height:
   100dvh` and the 760 block adds `height: 100dvh` WITHOUT clearing it, so the
   min-height survives into the desktop form and clamps anything shorter. In the
   product the two are the same number and the clamp is invisible, which is why it
   has never shown; the moment anything asks the shell to be shorter than the
   window, the min-height and not the height is what answers. Recorded here rather
   than "fixed" in app-shell.css, because in a build the two agreeing is correct
   and there is nothing to repair.
   ============================================================================ */
@container (min-width: 760px) {
  .stage-app .app {
    min-height: calc(100vh - var(--c-toggle-h));
    min-height: calc(100dvh - var(--c-toggle-h));
    height: calc(100vh - var(--c-toggle-h));
    height: calc(100dvh - var(--c-toggle-h));
  }
}

/* ---------- the stage the screen stands in --------------------------------
   `.stage` declares `container-type: inline-size`, and after the migration that
   is the SECOND container on the page: `base.css` declares one on `body`. That
   is correct and it is not a duplicate. The nearest ancestor container wins, so
   on a reviewed page every query reads `.stage`, exactly as it does today, and
   zero pixels move. `body` is there for the build, where this file does not
   exist and `.stage` never appears. The two boxes differ by this element's 32px
   of side padding, which was walked at 33 widths in 8px steps through all three
   breakpoint bands before the body container was declared. */
.layout { display: block; }
.stage { padding: 28px 16px 56px; container-type: inline-size; }
.stage.stage-app { padding: 0; }
/* The landing is flush for the same reason a screen is: it draws its own full
   bleed bands, and a review frame that inset them would show a page nobody gets.
   Added 2026-08-14 with the coloured landing; the grey has carried the class
   since round 3 (wireframes/_wf.css:37). */
.stage.stage-flush { padding: 0; }

/* ---------- where a wait goes, and it is the stand talking -----------------
   2026-08-19. The founder, standing on `connect-bank-loading`: "для меня тупик
   ... а что тут может быть дальше - success или ошибка или что-то еще, как
   сделать так, чтобы это не шло как в продукт, но было понятно, куда двигаться
   дальше". The dead end is correct and it is usage rule U7: a wait carries no
   control, because an edge the system takes is not one. Exactly two coloured
   screens have no link out of `.app` and both are U7's own pages.

   So the way forward is the REVIEWER'S and never the product's. `design/_nav.js`
   builds this strip outside `.app`, from data it holds itself, and adds nothing
   to any of the 57 screen files - no markup, no class, no link. Turn the chrome
   off and the wait is the wait that ships.

   IT IS FIXED AND IT IS IN THE CORNER, and both are for the same reason. The
   stage gives `.app` exactly `100dvh - var(--c-toggle-h)` past a 760px
   container, so a strip in normal flow under the screen would push the review
   page taller than the window - the exact +40px defect the toggle's own
   subtraction exists to cure, three rules above this one. A fixed box takes no
   height at all. The corner keeps it clear of the 250px rail on the left and of
   a tab bar at the foot, which no dead-end screen has anyway.

   z-index 140: under the drawer (200) and under its overlay (150), over the
   toggle strip (100). A reviewer who opens the screen list is not asking to read
   this at the same time.

   The palette is the chrome's own `--c-` set, so it follows the theme switch
   with the panel and cannot be mistaken for the product: the product's own
   surfaces are `--bg-*` and nothing in `design/system/` is drawn in sage. */
.scr-next {
  position: fixed; right: 16px; bottom: calc(16px + var(--lift, 0px)); z-index: 140;
  width: min(340px, calc(100vw - 32px));
  box-sizing: border-box;
  padding: 13px 15px 11px;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(20, 27, 29, 0.06), 0 14px 34px -16px rgba(20, 27, 29, 0.40);
}
.scr-next-h {
  margin: 0 0 6px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--c-accent);
}
.scr-next-w { margin: 0 0 10px; font-size: 12px; line-height: 1.45; color: var(--c-text-secondary); }
.scr-next-d { display: grid; gap: 4px; }
.scr-next-d a {
  display: block; text-decoration: none;
  padding: 7px 9px; border-radius: var(--c-radius-sm);
  border: 1px solid var(--c-border-light);
  transition: background 0.15s, border-color 0.15s;
}
.scr-next-d a:hover { background: var(--c-accent-light); border-color: var(--c-accent); }
.scr-next-d a:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.scr-next-d b { display: block; font-size: 12.5px; font-weight: 600; color: var(--c-text); }
.scr-next-d span { display: block; font-size: 11.5px; color: var(--c-text-muted); }

/* The chrome's own motion guard. `base.css` carries the global one for the
   product; this covers the drawer, which the product does not know about. */
@media (prefers-reduced-motion: reduce) {
  .sidebar, .sidebar-nav a { transition: none; }
}
