/* design/kit/_page.css - stand chrome ONLY.
   Nothing in this file describes a product component. Product classes live in
   design/system/components/; if a rule here starts styling a .pcard or a .btn,
   that is the defect the stage warns about, in the direction nobody checks.
   Every value below reads a token, because the stand is the first consumer of
   the system and a stand that does not eat its own tokens proves nothing.
   No em dash in this file. */

.kp{ min-height:100vh; }

/* ---------------- the ink of a colour sample (color.html) ----------------
   THE STAND OWNS THIS PAIR, AND THAT IS THE POINT. color.html paints a label
   ON a swatch, and the swatch is a raw primitive on display - not a surface
   the product owns and not one the theme moves. Its ink therefore belongs to
   the thing that shows it, the same call step 7.9 made when the stand frame
   got five `--stand-*` variables instead of borrowing product roles.

   IT USED TO BORROW, and the borrowing was visible in the numbers. The page
   chose between `--text-onaction-ink` and `--text-onaction` - a pair picked
   for one true property, «this ground does not move», and for a name that
   says «the label on the ACTION fill», which a swatch is not. The deepest ink
   in that pair is `--charcoal`, and `--charcoal` cannot lift `--slate-400`:
   4.41 against a bar of 4.5, with white at 3.86 on the other side.

   `--warm-950` is the system's deepest value and it is already an ink in
   everything but name - `--line-onink` reads it. On `--slate-400` it measures
   5.05, and because it is darker than `--charcoal` everywhere, no swatch that
   passed can fail. NO NEW VALUE ENTERS: both halves are primitives the file
   above already declares.

   DECLARED ONCE, WITH NO DARK HALF, ON PURPOSE - the 7.19 rule. A role whose
   two halves are identical is saying «my ground does not move», and a swatch
   is the purest case of that in the repository: it IS the value. */
:root{
  --stand-swatch-ink:   var(--warm-950);
  --stand-swatch-onink: var(--white);
}

/* ---------------- side panel (kit registry) ---------------- */
#kitnav{ position:fixed; inset:0 auto 0 0; width:236px; overflow-y:auto; z-index:40;
  background:var(--bg-surface); border-right:1px solid var(--line-hair);
  padding:var(--space-16) var(--space-16) var(--space-32); }
.kn-back{ display:inline-flex; align-items:center; gap:var(--space-8);
  font-size:var(--fs-12); font-weight:var(--fw-black); color:var(--text-action);
  margin-bottom:var(--space-16); }
.kn-back:hover{ text-decoration:underline; }
.kn-t{ font-family:var(--font-display); font-size:var(--fs-18); font-weight:var(--fw-bold);
  color:var(--text-primary); margin-bottom:var(--space-4); }
.kn-sub{ font-size:var(--fs-12); color:var(--text-muted); margin-bottom:var(--space-12);
  font-family:var(--font-mono); }
/* the theme switch of the STAND. Every colour here is a role, like everywhere
   else, so the button restyles itself when it flips the theme it controls. */
.kn-theme{ display:flex; align-items:center; gap:var(--space-8); width:100%;
  margin-bottom:var(--space-16); padding:var(--space-8) var(--space-12);
  border:1px solid var(--line-hair); border-radius:var(--radius-8);
  background:var(--bg-surface); color:var(--text-secondary);
  font-family:inherit; font-size:var(--fs-12); font-weight:var(--fw-semibold);
  cursor:pointer; text-align:left; }
.kn-theme:hover{ border-color:var(--line-strong); color:var(--text-primary); }
.kn-theme:focus-visible{ outline:none; box-shadow:var(--ring-focus); }
/* the mark is a filled half-circle: one shape that reads as «two themes» in
   both themes, and it needs no glyph from the set. */
.kn-theme-i{ width:var(--size-20); height:var(--size-20); border-radius:var(--radius-circle);
  border:1.5px solid var(--line-strong); flex:none;
  background:linear-gradient(90deg, var(--text-primary) 50%, transparent 50%); }
.kn-theme[aria-pressed="true"] .kn-theme-i{ transform:rotate(180deg); }
.kn-g{ margin-top:var(--space-16); }
.kn-gh{ font-size:var(--fs-10); font-weight:var(--fw-black); letter-spacing:var(--ls-eyebrow);
  text-transform:uppercase; color:var(--text-muted); margin-bottom:var(--space-8);
  display:flex; justify-content:space-between; }
/* The `.7` here is gone for the reason the fades on color.html went, and it was
   found by the same probe in the same run: `--text-muted` measures 5.05 on the
   panel and .7 of it measures 2.84, so the counter was reading a third under
   the bar while the label beside it passed. Mono against caps, and the flex row
   pushing it to the far edge, already say «this is the count». */
.kn-gh i{ font-style:normal; font-family:var(--font-mono); }
/* The layout rule takes .kn-l, not a.kn-l: a not-done row is a <span> and it
   still has to be a row. Only the interactive part is scoped to the anchor. */
#kitnav .kn-l{ display:block; font-size:var(--fs-14); color:var(--text-secondary);
  padding:var(--space-4) var(--space-8); border-radius:var(--radius-4); border-left:2px solid transparent; }
#kitnav a.kn-l:hover{ background:var(--bg-sunken); color:var(--text-primary); }
#kitnav a.kn-l.on{ color:var(--text-primary); font-weight:var(--fw-bold);
  background:var(--bg-sunken); border-left-color:var(--text-action); }

/* 10.4: the sections of the page the panel is standing on. They only ever appear
   under the ACTIVE row, so the indent is what says «inside this page» - the same
   thing the root panel says with the same shape and its own class names. */
#kitnav .kn-ss{ padding:var(--space-2) 0 var(--space-8); }
#kitnav .kn-s{ display:block; padding:var(--space-2) var(--space-8) var(--space-2) var(--space-24);
  font-size:var(--fs-12); color:var(--text-muted); text-decoration:none; border-radius:var(--radius-4); }
#kitnav .kn-s:hover{ color:var(--text-primary); background:var(--bg-sunken); }
#kitnav .kn-s.is-current{ color:var(--text-action); font-weight:var(--fw-semibold); }

/* ---------------- page frame ---------------- */
.kp-main{ padding:var(--space-24) var(--space-16) var(--space-40); max-width:1020px; }
@media(min-width:900px){ .kp-main{ margin-left:236px; padding:var(--space-32) var(--space-32) var(--space-40); } }
/* BELOW 900 THE PANEL IS NOT A PANEL - step 7.3. `.kp-main` steps aside only
   above 900, but `#kitnav` was fixed at every width, so under 900 the registry
   lay ON TOP of the page and covered the first 236px of every line. Measured at
   360 on every stand page, not just this one: the showcase that has to prove the
   system works on a phone could not be read on a phone. Under 900 it becomes an
   ordinary block at the top of the document, bounded so it does not push the
   page it introduces off the screen. */
@media(max-width:899px){
  #kitnav{ position:static; inset:auto; width:auto; max-height:44vh;
    border-right:none; border-bottom:1px solid var(--line-hair); }
}
.kp-eyebrow{ font-size:var(--fs-12); font-weight:var(--fw-black); letter-spacing:var(--ls-eyebrow);
  text-transform:uppercase; color:var(--text-muted); }
.kp-h1{ font-family:var(--font-display); font-size:var(--fs-34); font-weight:var(--fw-bold);
  letter-spacing:var(--ls-lead); color:var(--text-primary); margin:var(--space-4) 0 var(--space-8); }
.kp-lead{ font-size:var(--fs-14); color:var(--text-secondary); max-width:72ch; }
.kp-lead b{ color:var(--text-primary); }
.kp-meta{ display:flex; flex-wrap:wrap; gap:var(--space-8); margin-top:var(--space-16); }
.kp-tag{ font-family:var(--font-mono); font-size:var(--fs-12); color:var(--text-secondary);
  background:var(--bg-sunken); border-radius:var(--radius-pill); padding:var(--space-4) var(--space-12); }

.kp-sec{ margin-top:var(--space-32); padding-top:var(--space-16); border-top:2px solid var(--line-hair); }
.kp-sh{ font-size:var(--fs-12); font-weight:var(--fw-black); letter-spacing:var(--ls-eyebrow);
  text-transform:uppercase; color:var(--text-muted); margin-bottom:var(--space-12); }
.kp-sh b{ color:var(--text-action); }
.kp-p{ font-size:var(--fs-14); color:var(--text-secondary); max-width:76ch; margin-bottom:var(--space-12); }
.kp-p b{ color:var(--text-primary); }
/* a heading INSIDE a section - a section that answers three questions needs to
   say where one answer ends. Not a second `.kp-sh`: that one names the section
   in the sidebar's language, and two of them in a row would read as two
   sections. */
.kp-sh2{ font-size:var(--fs-16); font-weight:var(--fw-bold); color:var(--text-primary);
  margin:var(--space-24) 0 var(--space-8); }
.kp-sec > .kp-sh2:first-of-type{ margin-top:var(--space-16); }

/* live specimen */
.kp-demo{ border:1px solid var(--line-hair); border-radius:var(--radius-12);
  background:var(--bg-page); padding:var(--space-24); margin-bottom:var(--space-12); }
.kp-demo.sunk{ background:var(--bg-sunken); }
.kp-demo.dark{ background:var(--bg-inverse); }
.kp-row{ display:flex; flex-wrap:wrap; gap:var(--space-16); align-items:flex-start; }
.kp-cap{ font-family:var(--font-mono); font-size:var(--fs-12); color:var(--text-muted);
  margin-top:var(--space-8); }

/* anatomy callouts */
.kp-anat{ display:grid; gap:var(--space-8); }
.kp-anat .a{ display:grid; grid-template-columns:22px 1fr; gap:var(--space-12); align-items:baseline;
  font-size:var(--fs-14); color:var(--text-secondary); }
.kp-anat .a i{ font-style:normal; width:22px; height:22px; border-radius:var(--radius-circle);
  background:var(--bg-action); color:var(--text-oninverse); font-size:var(--fs-12);
  font-weight:var(--fw-black); display:flex; align-items:center; justify-content:center; }
.kp-anat .a b{ color:var(--text-primary); }

/* tables */
.kp-tbl{ width:100%; border-collapse:collapse; font-size:var(--fs-14); }
.kp-tbl th{ text-align:left; font-size:var(--fs-12); font-weight:var(--fw-black);
  letter-spacing:var(--ls-caps); text-transform:uppercase; color:var(--text-muted);
  padding:var(--space-8) var(--space-12); border-bottom:1px solid var(--line-strong); }
.kp-tbl td{ padding:var(--space-8) var(--space-12); border-bottom:1px solid var(--line-hair);
  color:var(--text-secondary); vertical-align:top; }
.kp-tbl td b{ color:var(--text-primary); }
.kp-tbl code{ font-family:var(--font-mono); font-size:var(--fs-12); color:var(--text-primary); }
.kp-scroll{ overflow-x:auto; }

/* rule / anti-rule */
.kp-pair{ display:grid; gap:var(--space-12); }
@media(min-width:760px){ .kp-pair{ grid-template-columns:1fr 1fr; } }
.kp-do,.kp-dont{ border-radius:var(--radius-12); padding:var(--space-16) var(--space-16);
  font-size:var(--fs-14); }
.kp-do{ background:var(--bg-success); border:1px solid var(--line-success); color:var(--text-secondary); }
.kp-dont{ background:var(--bg-danger); border:1px solid var(--line-danger); color:var(--text-secondary); }
.kp-do h4,.kp-dont h4{ font-size:var(--fs-12); font-weight:var(--fw-black); letter-spacing:var(--ls-caps);
  text-transform:uppercase; margin-bottom:var(--space-8); }
.kp-do h4{ color:var(--text-success); }
.kp-dont h4{ color:var(--text-danger); }
.kp-do b,.kp-dont b{ color:var(--text-primary); }

/* code */
.kp-code{ background:var(--bg-inverse); color:var(--bg-sunken); border-radius:var(--radius-8);
  padding:var(--space-12) var(--space-16); font-family:var(--font-mono); font-size:var(--fs-12);
  line-height:var(--lh-snug); overflow-x:auto; white-space:pre; }

/* gap note - what stage 09 has to add */
.kp-gap{ border:1px dashed var(--line-strong); border-radius:var(--radius-12);
  background:var(--bg-surface); padding:var(--space-16) var(--space-16); font-size:var(--fs-14);
  color:var(--text-secondary); }
.kp-gap h4{ font-size:var(--fs-12); font-weight:var(--fw-black); letter-spacing:var(--ls-caps);
  text-transform:uppercase; color:var(--text-muted); margin-bottom:var(--space-8); }
.kp-gap ul{ margin:var(--space-8) 0 0 var(--space-16); }
.kp-gap li{ margin-bottom:var(--space-4); }
.kp-gap b{ color:var(--text-primary); }

/* TWO COLUMNS THAT STAY TWO - step 7.36.
   For a demo where the PAIRING is the point: the same component with a fact and
   without it, side by side, so the difference is read rather than described.
   `.kp-grid` above auto-fills and would reflow a pair into three columns, which
   silently breaks the comparison. Collapses to one column under 560, where two
   columns of a price block stop being legible anyway. The label goes ABOVE its
   cell - `.kp-cap` sits below and is a caption for the demo, not a name for a
   thing inside it. */
.kp-2col{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--space-16) var(--space-24); }
@media (max-width:560px){ .kp-2col{ grid-template-columns:1fr; } }
.kp-lbl{ font-family:var(--font-mono); font-size:var(--fs-12); color:var(--text-muted);
  margin-bottom:var(--space-8); }

/* hub cards */
.kp-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(216px,1fr)); gap:var(--space-12); }
a.kp-card{ display:block; border:1px solid var(--line-hair); border-radius:var(--radius-12);
  background:var(--bg-page); padding:var(--space-16) var(--space-16); }
a.kp-card:hover{ border-color:var(--line-action); }
.kp-card .n{ font-size:var(--fs-14); font-weight:var(--fw-bold); color:var(--text-primary); }
.kp-card .f{ font-family:var(--font-mono); font-size:var(--fs-12); color:var(--text-muted);
  margin-top:var(--space-2); }
.kp-card .d{ font-size:var(--fs-12); color:var(--text-secondary); margin-top:var(--space-8); }
.kp-card .m{ font-family:var(--font-mono); font-size:var(--fs-12); color:var(--text-muted);
  margin-top:var(--space-8); display:flex; gap:var(--space-12); }

/* Panels on a stand - step 7.86.
   Sixteen organisms do not exist at rest: they are `display: none` until something
   adds `.open`, and most of them are `position: fixed`. The first draft of this rule
   laid them out in flow - `position: static; inset: auto` - and measurement killed
   it: eleven of them collapsed to zero height, because a panel that is positioned by
   `inset: 0` or by `top/bottom` has no height of its own once you take the position
   away. The frame must not redraw the thing it frames.
   So both names below resolve to ONE mechanism, the stage: a transformed ancestor
   becomes the containing block for a fixed descendant, and the panel keeps every
   declaration it has, including where it stands. */
.kp-demo--panel{ }

/* A stage for a panel that is `position: fixed` - step 7.86.
   Four organisms (auth dialog, city dialog, review modal, scrim) are fixed and
   `inset: 0`. Opened inside a plain demo box they leave it and cover the whole
   stand: measured at 390 and 1280, the scrim painted 52% ink over the page at
   z 60, above the panel of the showcase itself. A TRANSFORMED ancestor becomes
   the containing block for a fixed descendant, so the stage below catches them:
   `.auth-ov` and `.wf-ov` land exactly inside it at both widths.
   It does NOT catch everything, and that is worth saying out loud: `.wf-city` and
   `.pm` size themselves in 94vw / 86vh / 88vh, and vw/vh stay relative to the
   VIEWPORT inside a transformed ancestor. Those two are shown at their real size
   and the stage scrolls; a 94vw dialog cannot fit a 358px column at 390 and no
   frame rule can change that. */
.kp-demo.kp-stage, .kp-demo.kp-demo--panel, .kp-demo.panel{ position:relative; transform:translateZ(0); overflow:auto;
  height:min(92vh, 720px); padding:0; background:var(--bg-sunken); }

/* The demo frame - step 7.86, and the owner found the defect that made it necessary.
   `.wf-tabbar` and `.fsheet` are `display: none` from 860. Shown inside a stand whose
   own viewport is 1280 they correctly drew NOTHING, and the page said nothing about it:
   a blank box that reads as a broken stand and is in fact the component behaving exactly
   as written. A media query reads the viewport, never the container, so no rule of the
   showcase can answer it. An iframe has a viewport of its own, so the frame below is
   the answer: each demo declares the width it is shown at, and that width is the one
   the component lives at in the product. */
.kp-frame-wrap{ border:1px solid var(--line-hair); border-radius:var(--radius-12);
  background:var(--bg-sunken); padding:var(--space-12); overflow:hidden; position:relative; }
.kp-frame{ display:block; border:0; background:var(--bg-page);
  border-radius:var(--radius-8); height:640px; }

/* THE BEFORE / AFTER WIPE - step 7.94, `pixel-proof.html`.
   Two photographs of the same screen from two trees, one on top of the other, and
   the top one clipped by a handle the reader drags. A pair of images side by side
   asks the eye to hold two things at once and compare them from memory; a wipe puts
   the difference on ONE set of coordinates, so a 4px shift is a 4px shift and not a
   feeling. The slider is a real `input[type=range]`: it comes with a keyboard, an
   accessible name and a focus ring already, and none of that had to be built. */
.pp-cmp{ position:relative; aspect-ratio:390/844; border-radius:var(--radius-8);
  overflow:hidden; background:var(--bg-sunken); border:1px solid var(--line-hair); }
.pp-cmp img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  object-position:top center; display:block; }
.pp-cmp .pp-b{ clip-path:inset(0 0 0 var(--p, 50%)); }
.pp-cmp .pp-r{ position:absolute; inset:0; width:100%; height:100%; margin:0; opacity:0;
  cursor:ew-resize; -webkit-appearance:none; appearance:none; background:none; z-index:3; }
.pp-cmp .pp-r:focus-visible{ opacity:1; outline:none; }
.pp-cmp .pp-r:focus-visible + .pp-h{ box-shadow:var(--ring-focus-control); }
.pp-cmp .pp-h{ position:absolute; top:0; bottom:0; left:var(--p, 50%); width:2px;
  background:var(--bg-action); z-index:2; pointer-events:none; }
.pp-cmp .pp-h::after{ content:''; position:absolute; top:50%; left:50%; width:var(--size-26);
  height:var(--size-26); margin:calc(var(--size-26) / -2) 0 0 calc(var(--size-26) / -2);
  border-radius:var(--radius-pill); background:var(--bg-action); }
.pp-cmp .pp-t{ position:absolute; top:var(--space-8); z-index:2; font-size:var(--fs-10);
  font-weight:var(--fw-black); text-transform:uppercase; letter-spacing:var(--ls-caps);
  padding:var(--space-2) var(--space-8); border-radius:var(--radius-pill);
  background:var(--bg-inverse); color:var(--text-oninverse); }
.pp-cmp .pp-t.l{ left:var(--space-8); }
.pp-cmp .pp-t.r{ right:var(--space-8); }
.pp-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(230px, 1fr));
  gap:var(--space-16); }
.pp-cell .n{ font-weight:var(--fw-black); font-size:var(--fs-14); margin-top:var(--space-8); }
.pp-cell .d{ font-size:var(--fs-12); color:var(--text-muted); margin-top:var(--space-2); }
.pp-cell .d b{ color:var(--text-body); font-family:var(--font-mono); }
/* The score card: one claim, its two numbers and the arrow between them. */
.pp-score{ display:grid; grid-template-columns:repeat(auto-fill, minmax(240px, 1fr));
  gap:var(--space-12); }
.pp-s{ border:1px solid var(--line-hair); border-radius:var(--radius-12);
  padding:var(--space-16); background:var(--bg-page); }
.pp-s .k{ font-size:var(--fs-12); color:var(--text-muted); }
.pp-s .v{ display:flex; align-items:baseline; gap:var(--space-8); margin-top:var(--space-4);
  font-family:var(--font-mono); font-variant-numeric:tabular-nums; }
.pp-s .v .was{ font-size:var(--fs-20); color:var(--text-muted); text-decoration:line-through;
  text-decoration-color:var(--line-strong); }
.pp-s .v .ar{ color:var(--mark-faint); font-weight:var(--fw-bold); }
.pp-s .v .now{ font-size:var(--fs-30); font-weight:var(--fw-bold); color:var(--text-body); }
.pp-s .w{ font-size:var(--fs-12); color:var(--text-secondary); margin-top:var(--space-8);
  line-height:var(--lh-snug); }
.pp-s.good .v .now{ color:var(--text-action); }

/* The move table - step 7.94. Six columns did not fit 1280 and the reason column,
   which is the only one worth reading twice, was the one that fell off the right
   edge into the scroller. Four columns fit: the variable rides under the clause
   it belongs to, and the two values share one cell with the arrow between them,
   which is how every other page in this kit already writes a change. */
.pp-mv{ table-layout:fixed; }
.pp-mv th:nth-child(1), .pp-mv td:nth-child(1){ width:52px; }
.pp-mv th:nth-child(2), .pp-mv td:nth-child(2){ width:30%; }
.pp-mv th:nth-child(3), .pp-mv td:nth-child(3){ width:26%; }
.pp-mv code{ display:inline-block; margin-top:var(--space-4); }
.pp-mv .fromto{ display:grid; gap:var(--space-2); font-family:var(--font-mono); font-size:var(--fs-12);
  /* a token list has no spaces to break at, so on a phone the cell walked 148px
     past its own box - inside a scroller, where nobody would look for it */
  overflow-wrap:anywhere; }
.pp-mv .fromto .f{ color:var(--text-muted); }
.pp-mv .fromto .t{ color:var(--text-body); font-weight:var(--fw-semibold); }
.pp-mv .fromto .t::before{ content:'\2192\00a0'; color:var(--mark-faint); font-weight:var(--fw-bold); }
