/* ============================================================
   howto.css — the "How it works" window: a software panel that opens over the
   page and plays the switch as seven steps on one timeline you can drive.

     1 · mapping      the systems you run today, found and lined up
     2 · migration    we move each one across, then the card steps aside
     3 · test & live  staff sign each one off, a hand presses go live, confetti
     4 · ask          the KompanyOS card reshapes INTO the software window
     5 · change       a field added in plain words, live
     6 · self-heal    the fault at the top, then a field of records filling the
                      panel; it sweeps them, catches one, and fixes it
     7 · recap        the six steps again, and a way back to the top

   A retro transport sits at the bottom: play/pause, a chunky scrub bar with a
   milestone per step. It autoplays, and dragging takes over.

   Chrome is .kos-howto*; the scenes and the transport are .kh-*.

   Shared, self-contained, token-independent: every colour/font reads the 3SC
   token when present (--cube-*), falls back to the page's own alias, then to a
   brand hex — so it renders on any ground. The retro surfaces follow retro.css's
   house rules: flat fills, 3px keylines, depth by offset, pressed = translate +
   shadow collapse.

   Pair with howto.js. Used by index.html and school.html; demo in styles.html §20.
   ============================================================ */

.kos-howto {
  --kh-ink: var(--cube-ink, var(--ink, #0a0a0a));
  --kh-pink: var(--cube-pink, var(--pink, #f70087));
  --kh-green: var(--cube-green, var(--green, #00ed71));
  --kh-yellow: var(--cube-yellow, var(--yellow, #ffd100));
  --kh-purple: var(--cube-secondary-purple, #9747ff);
  --kh-blue: var(--cube-cat-blue, #00a3ff);
  --kh-orange: var(--cube-cat-orange, #ff7a00);
  --kh-dim: var(--cube-gray-600, #5b5b5b);
  --kh-face: #fff;
  --kh-sub: var(--cube-gray-50, #f8f8f8);
  --kh-well: var(--cube-gray-100, #ededed);
  --kh-font: var(--cube-font-primary, var(--font, 'Poppins', system-ui, sans-serif));
  --kh-mono: var(--cube-font-secondary, var(--mono, 'Anonymous Pro', ui-monospace, monospace));

  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(12px, 3vw, 40px);
  background: rgba(0, 0, 0, .55);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .18s ease;
}
.kos-howto[hidden] { display: none; }
.kos-howto.is-open { opacity: 1; }

/* ============================================================
   The window
   ============================================================ */
.kos-howto-win {
  position: relative;
  display: flex; flex-direction: column;
  /* Fixed height, not max-height: the window is the same size whatever the
     timeline is showing, so it never resizes under the reader. */
  width: 100%; max-width: 1040px; height: min(88vh, 860px);
  background: var(--kh-face); color: var(--kh-ink);
  border: 3px solid #000; border-radius: 18px;
  overflow: hidden;
  /* grows out of the button you clicked — howto.js sets transform-origin */
  transform: scale(.16); opacity: 0;
  transition: transform .38s cubic-bezier(.2, 1.15, .3, 1), opacity .2s ease;
}
.kos-howto.is-open .kos-howto-win { transform: none; opacity: 1; }

/* White, and no rule under it: the body's dotted ground is what separates the
   two, so the join doesn't need a line drawn across it. */
.kos-howto-bar {
  flex: none; display: flex; align-items: center; gap: 8px;
  padding: 12px clamp(14px, 2vw, 20px);
  background: var(--kh-face);
}
.kos-howto-dots { display: flex; gap: 8px; flex: none; }
.kos-howto-dots i {
  width: 12px; height: 12px; border-radius: 50%; border: 2px solid #000;
  display: block; transform: scale(.2); opacity: 0;
  transition: transform .26s cubic-bezier(.2, 1.6, .4, 1), opacity .16s ease;
}
.kos-howto-dots i:nth-child(1) { background: #ff5f57; transition-delay: .10s; }
.kos-howto-dots i:nth-child(2) { background: var(--kh-yellow); transition-delay: .16s; }
.kos-howto-dots i:nth-child(3) { background: var(--kh-green); transition-delay: .22s; }
.kos-howto.is-open .kos-howto-dots i { transform: none; opacity: 1; }

.kos-howto-name {
  flex: 1 1 auto; min-width: 0; margin-left: 6px;
  font: 700 12px/1.3 var(--kh-mono); text-transform: uppercase; letter-spacing: .1em;
  color: var(--kh-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Just the glyph — a bordered, 900-weight box shouted louder than the title. */
.kos-howto-x {
  flex: none; width: 36px; height: 36px; display: inline-flex;
  align-items: center; justify-content: center;
  border: 0; border-radius: 8px; background: transparent;
  font: 400 27px/1 var(--kh-font); color: var(--kh-ink); cursor: pointer;
  transition: background .16s ease;
}
.kos-howto-x:hover { background: rgba(0, 0, 0, .06); }
.kos-howto-x:focus-visible { outline: 2px solid var(--kh-pink); outline-offset: 2px; }

.kos-howto-body {
  /* min-height:0 or the flex item refuses to shrink below its content height,
     the window outgrows its own max-height, and the stage is clipped. */
  flex: 1 1 auto; min-height: 0; overflow: hidden;
  /* their Section variant="gray-dot" — the 40px dotted ground, same recipe as
     cube-kit.css's .cube-section-graydot and the ground visuals/ is drawn on.
     Mirrored, not linked: this file has to stand on its own. */
  background-color: var(--cube-gray-200, #f8f8f8);
  background-image:
    radial-gradient(rgba(0, 0, 0, .10) 1.5px, transparent 0),
    radial-gradient(rgba(0, 0, 0, .10) 1.5px, transparent 0);
  background-position: 0 0, 20px 20px;
  background-size: 40px 40px, 40px 40px;
  opacity: 0; transform: translateY(10px);
  transition: opacity .3s ease .12s, transform .34s cubic-bezier(.22, 1, .36, 1) .12s;
}
.kos-howto.is-open .kos-howto-body { opacity: 1; transform: none; }

/* ============================================================
   The stage — every scene is a layer in the same box, so the geometry lines
   up across a cut and objects appear to carry over.
   ============================================================ */
.kh-stage { position: relative; width: 100%; height: 100%; }
.kh-scene {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
}
.kh-scene[hidden] { display: none; }

/* The words are a CARD standing on the dotted ground, not a white band ruled
   off from it — the same object language as everything else in the window. The
   band it sits in keeps its FIXED height, so the stage below never shifts when
   one step's heading is a line longer than the next one's. That shift was the
   jump between the column and the migration. */
/* Sized off the VIEWPORT HEIGHT, not the width. The window is min(88vh, 860),
   so on a 667-tall laptop the stage is ~246px and a flat 104px band plus a flat
   123px transport took most of it — the card ended up 122px tall needing 156,
   and its tiles overflowed it. Everything here gives a little when the screen
   is short. */
.kh-head {
  flex: none; height: var(--kh-headh, clamp(74px, 11.5vh, 104px));
  display: flex; align-items: center; justify-content: center;
  padding: clamp(7px, 1.4vh, 18px) clamp(18px, 3vw, 40px) clamp(6px, 1.1vh, 10px);
  background: transparent;
}
.kh-head-card {
  position: relative; width: 100%; max-width: 780px; height: 100%;
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  text-align: center;
  padding: clamp(6px, 1.1vh, 16px) clamp(18px, 2.6vw, 30px);
  background: var(--kh-face);
  border: 3px solid #000; border-radius: 14px;
  box-shadow: 6px 6px 0 0 #000;
  /* the words slide in from off the card's own edges */
  overflow: hidden;
}
.kh-h {
  font: 800 clamp(16px, min(2vw, 2.6vh), 25px)/1.2 var(--kh-font); letter-spacing: -.02em;
  opacity: 0; transform: translateX(-42px);
}
/* The phrase that carries the step, UNDERLINED in the step's own colour — the
   same colour as its number under the bar. A rule, not a highlighter: the paint
   is parked BELOW the font's descent line (stickers.css's --kos-rule-drop idea)
   rather than at a percentage of the line box, which lands somewhere different
   in every font and is how a pink rule once struck through "KompanyOS". The
   drop is paid for in padding and taken straight back in margin, so the paint
   grows downwards and nothing reflows. Written out here rather than referenced,
   because this file has to stand on its own. */
.kh-h em {
  font-style: normal;
  padding-bottom: .22em; margin-bottom: -.22em;
  background-image: linear-gradient(to top,
    transparent .07em, var(--kh-hc, var(--kh-green)) .07em,
    var(--kh-hc, var(--kh-green)) .19em, transparent .19em);
  background-repeat: no-repeat;
  background-size: 0 100%;
}
/* Retriggered on every cut, so you SEE the chapter turn. Nine pixels of fade
   was unnoticeable — the title comes in from the side and the rule is drawn
   under it once it has landed. */
.kh-head.is-in .kh-h {
  opacity: 1; transform: none;
  transition: opacity .3s ease, transform .5s cubic-bezier(.22, 1, .36, 1);
}
.kh-head.is-in .kh-h em {
  background-size: 100% 100%;
  transition: background-size .45s cubic-bezier(.22, 1, .36, 1) .3s;
}

.kh-play-area {
  position: relative; flex: 1 1 auto; min-height: 0;
  margin: clamp(10px, 1.7vh, 22px) clamp(18px, 3vw, 40px) clamp(12px, 2vh, 26px);
}

/* --- the card every system is drawn as (scenes 1 and 2) --- */
.kh-sys {
  position: absolute; left: 0; top: 0;
  width: var(--kh-sysw, 186px);
  display: grid; grid-template-columns: 26px 1fr auto; gap: 9px; align-items: center;
  padding: 9px 11px;
  background: var(--kh-face); border: 2.5px solid #000; border-radius: 10px;
  box-shadow: 4px 4px 0 0 #000;
  /* a short window caps the row height (howto.js), and a card is a card — it
     clips rather than letting its own words hang out of the bottom */
  overflow: hidden;
  will-change: transform;
}
/* the compact row, for windows that cannot give five cards their full height */
.kh-sys.is-tight { padding: 5px 10px; grid-template-columns: 21px 1fr auto; gap: 8px; }
.kh-sys.is-tight .kh-sys-ic { width: 21px; height: 21px; border-radius: 5px; font-size: 10px; }
.kh-sys-ic {
  width: 26px; height: 26px; border-radius: 6px; border: 2px solid #000;
  background: var(--sc, var(--kh-green));
  display: inline-flex; align-items: center; justify-content: center;
  font: 800 11px/1 var(--kh-font); color: var(--si, #000);
}
.kh-sys-nm {
  font: 700 11.5px/1.2 var(--kh-font); letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kh-sys-st { font: 700 9px/1 var(--kh-mono); text-transform: uppercase; letter-spacing: .1em; color: var(--kh-dim); }

/* ============================================================
   Scene 2 — migration. Three columns: what you run, the core, the sign-offs.
   ============================================================ */
.kh-core {
  position: absolute; overflow: hidden;
  background: var(--kh-face); border: 3px solid #000; border-radius: 14px;
  box-shadow: 6px 6px 0 0 #000;
}
.kh-core canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.kh-core-lbl {
  position: absolute; inset: auto 0 0 0; padding: 10px 12px;
  display: flex; align-items: center; justify-content: center;
  border-top: 2px solid #000; background: var(--kh-face);
}
/* the real wordmark, not Poppins pretending to be it */
.kh-core-lbl img { width: 100%; max-width: 132px; height: auto; display: block; }

/* what has landed, stacking up inside the core over the flood */
/* the bottom inset is set by howto.js from the wordmark bar's MEASURED height,
   so the tiles can never be handed less room than they need */
.kh-core-pile {
  position: absolute; inset: 8px 8px 46px; z-index: 1;
  display: flex; flex-direction: column-reverse; justify-content: center;
  gap: var(--pile-gap, 4px);
  overflow: hidden;
}
.kh-mini {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 7px; border: 2px solid #000; border-radius: 6px;
  background: var(--kh-face); box-shadow: 2px 2px 0 0 #000;
  font: 700 9.5px/1.2 var(--kh-font); letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kh-mini i { flex: none; width: 9px; height: 9px; border-radius: 3px; border: 1.5px solid #000; background: var(--sc, var(--kh-green)); }
/* the compact tile, for a card too short to give five of them their full height */
.kh-mini.is-tight { padding: 2px 6px; gap: 5px; font-size: 8.5px; border-width: 1.5px; box-shadow: 1.5px 1.5px 0 0 #000; }
.kh-mini.is-tight i { width: 7px; height: 7px; border-width: 1px; }


/* a pill, so the column header is legible against the dotted ground instead of
   dissolving into it */
.kh-colhead {
  position: absolute; display: inline-flex; align-items: center; justify-content: center;
  white-space: nowrap; transform: translateX(-50%);
  padding: 4px 9px; border: 2px solid #000; border-radius: 999px;
  background: var(--kh-face); box-shadow: 2px 2px 0 0 #000;
  font: 800 9px/1.15 var(--kh-font); text-transform: uppercase; letter-spacing: .06em;
  color: var(--kh-ink); text-align: center; gap: 4px;
}
/* the emoji rides at its own size — at the pill's 9px it is unreadable */
.kh-colhead b { font-size: 12px; line-height: 1; font-weight: 400; }
/* the same treatment naming the source column */
.kh-collbl {
  position: absolute; left: 0; top: 0; display: inline-flex; align-items: center;
  padding: 4px 9px; border: 2px solid #000; border-radius: 999px;
  background: var(--kh-yellow); box-shadow: 2px 2px 0 0 #000;
  font: 800 9px/1.15 var(--kh-font); text-transform: uppercase; letter-spacing: .06em;
  color: var(--kh-ink); white-space: nowrap;
}

/* It went live, and it says so — as a NOTIFICATION, not another button. A green
   fill with a 3px keyline and a hard offset shadow is this kit's button, so it
   read as one thing to press next to the thing you had just pressed. Dark
   ground, light text, the tick carrying the green. */
.kh-toast {
  position: absolute; left: 0; top: 0; opacity: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 10px 16px; border: 0; border-radius: 10px;
  background: var(--kh-ink); color: #fff;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .28);
  font: 600 12px/1.2 var(--kh-font); letter-spacing: -.01em;
  white-space: nowrap;
}
/* the emoji carries it, so no green disc behind it */
.kh-toast b { flex: none; font: 400 15px/1 var(--kh-font); }
/* A sign-off cell. It used to flip in one frame — the well changed colour and
   the tick appeared — and five of those in a row read as a strobe rather than
   five decisions. Now the colour FLOODS the well from the bottom (--f, driven
   from howto.js) and the tick is stamped on it a beat later; the shadow grows
   with the fill, so the cell rises off the ground as it fills. */
.kh-cell {
  position: absolute; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2.5px solid #000; border-radius: 8px;
  background-color: var(--kh-well);
  background-image: linear-gradient(to top,
    var(--cc, var(--kh-green)) var(--f, 0%), transparent var(--f, 0%));
}
.kh-cell i {
  font: 800 13px/1 var(--kh-font); font-style: normal; color: #000;
  display: block; opacity: 0;
}


/* The hand that presses it. Pointer-events off — it is a picture of somebody
   doing it, not something to click. */
.kh-hand {
  position: absolute; left: 0; top: 0; opacity: 0;
  width: 30px; height: 30px; pointer-events: none; z-index: 4;
  filter: drop-shadow(2px 3px 0 rgba(0, 0, 0, .22));
}
.kh-hand img { width: 100%; height: 100%; display: block; }

/* one piece of confetti: a flat square in a brand colour, thrown by howto.js */
.kh-conf {
  position: absolute; left: 0; top: 0; opacity: 0;
  border: 1.5px solid #000; border-radius: 1px;
  pointer-events: none; z-index: 5;
  will-change: transform;
}

/* go-live: a retro button, disabled until every check is in */
.kh-golive {
  position: absolute;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 18px; cursor: default;
  border: 3px solid #000; border-radius: 10px;
  background: var(--kh-well); color: #9b9b9b;
  font: 800 12px/1 var(--kh-font); text-transform: uppercase; letter-spacing: .06em;
  box-shadow: 4px 4px 0 0 #000;
}
.kh-golive.is-ready { background: var(--kh-green); color: #000; }
/* depth by offset: pressed collapses the shadow and moves onto it (retro.css) */
.kh-golive.is-pressed { transform: translate(4px, 4px); box-shadow: 0 0 0 0 #000; }

/* ============================================================
   Scenes 3-5 — one app window that takes the screen and stays for all three.
   ============================================================ */
.kh-app {
  /* left/top/width/height, NOT inset: howto.js animates this box out of the
     KompanyOS card's own box, and an over-constrained inset fights it */
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--kh-face); border: 3px solid #000; border-radius: 12px;
  box-shadow: 6px 6px 0 0 #000;
  transform-origin: 50% 50%;
}
.kh-app.is-settled .kh-app-bar,
.kh-app.is-settled .kh-app-side,
.kh-app.is-settled .kh-pane { opacity: var(--kh-appin, 1); }
.kh-app-bar {
  flex: none; display: flex; align-items: center; gap: 7px;
  padding: 8px 11px; border-bottom: 2.5px solid #000; background: var(--kh-sub);
}
.kh-app-bar i { width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid #000; display: block; }
.kh-app-bar i:nth-child(1) { background: #ff5f57; }
.kh-app-bar i:nth-child(2) { background: var(--kh-yellow); }
.kh-app-bar i:nth-child(3) { background: var(--kh-green); }
.kh-app-nm { margin-left: 5px; font: 700 10px/1 var(--kh-mono); text-transform: uppercase; letter-spacing: .12em; color: var(--kh-dim); }
.kh-app-body { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: 118px 1fr; }
.kh-app-side { border-right: 2.5px solid #000; background: var(--kh-sub); padding: 10px 9px; display: grid; gap: 5px; align-content: start; }
.kh-app-side b {
  font: 700 9px/1 var(--kh-mono); text-transform: uppercase; letter-spacing: .12em;
  color: var(--kh-dim); padding: 3px 6px;
}
.kh-app-side span {
  padding: 6px 8px; border-radius: 6px;
  font: 600 11px/1.2 var(--kh-font); color: var(--kh-ink);
}
.kh-app-side span.on { background: var(--kh-pink); color: #fff; }
.kh-app-main { min-width: 0; padding: clamp(12px, 1.6vw, 18px); overflow: hidden; position: relative; }
.kh-pane { position: absolute; inset: clamp(12px, 1.6vw, 18px); }
.kh-app:not(.is-settled) .kh-app-bar,
.kh-app:not(.is-settled) .kh-app-side,
.kh-app:not(.is-settled) .kh-pane { opacity: 0; }
.kh-pane[hidden] { display: none; }

/* the ask bar the plain-words instruction is typed into */
.kh-ask {
  display: flex; align-items: center; gap: 9px;
  border: 2.5px solid #000; border-radius: 9px; background: var(--kh-face);
  padding: 9px 12px; box-shadow: 3px 3px 0 0 #000;
}
.kh-ask-ic { flex: none; font-size: 13px; }
.kh-ask-tx { font: 400 12.5px/1.3 var(--kh-mono); color: var(--kh-ink); white-space: nowrap; overflow: hidden; }
/* the caret only blinks while something is being typed */
.kh-caret { display: inline-block; width: 7px; margin-left: 1px; border-bottom: 2px solid var(--kh-ink); vertical-align: 2px; }
.kh-ask.is-typing .kh-caret { animation: khBlink .9s steps(1) infinite; }
@keyframes khBlink { 0%, 50% { opacity: 1 } 51%, 100% { opacity: 0 } }

/* the answer that assembles under it */
.kh-ans { margin-top: 13px; }
.kh-ans-big { font: 900 clamp(26px, 3.6vw, 44px)/1 var(--kh-font); letter-spacing: -.03em; }
.kh-ans-big small { font: 700 11px/1 var(--kh-mono); text-transform: uppercase; letter-spacing: .12em; color: var(--kh-dim); display: block; margin-bottom: 6px; }
/* the unit, so the number is obviously a count of something */
.kh-ans-big em { font: 800 clamp(13px, 1.5vw, 17px)/1 var(--kh-font); font-style: normal; letter-spacing: -.01em; color: var(--kh-dim); }
.kh-ans-rows { margin-top: 12px; display: grid; gap: 5px; }
.kh-ans-row {
  display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center;
  padding: 8px 11px; border: 2px solid #000; border-radius: 7px; background: var(--kh-face);
  font: 400 12px/1.2 var(--kh-mono);
}
.kh-ans-row b { font: 700 13px/1 var(--kh-mono); }

/* the form scene 4 rearranges */
.kh-form { margin-top: 13px; display: grid; gap: 7px; }
.kh-field {
  display: grid; grid-template-columns: 96px 1fr; gap: 10px; align-items: center;
  padding: 8px 10px; border: 2px solid #000; border-radius: 7px; background: var(--kh-face);
}
.kh-field b { font: 700 10px/1.2 var(--kh-mono); text-transform: uppercase; letter-spacing: .08em; color: var(--kh-dim); }
.kh-field span { height: 9px; border-radius: 4px; background: #dedede; }
.kh-field.is-new { border-color: var(--kh-pink); box-shadow: 3px 3px 0 0 var(--kh-pink); }
.kh-field.is-new b { color: var(--kh-pink); }
.kh-chip {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 12px;
  padding: 8px 14px; border: 2.5px solid #000; border-radius: 999px;
  background: var(--kh-green);
  font: 800 11px/1 var(--kh-font); text-transform: uppercase; letter-spacing: .07em;
  box-shadow: 3px 3px 0 0 #000;
}
.kh-chip.pink { background: var(--kh-pink); color: #fff; }

/* scene 5's fault banner */
.kh-alert {
  display: grid; grid-template-columns: 26px 1fr auto; gap: 10px; align-items: center;
  padding: 10px 12px; border: 2.5px solid #000; border-radius: 9px;
  background: #ffe1ec; box-shadow: 3px 3px 0 0 #000;
  font: 400 11.5px/1.35 var(--kh-mono);
}
.kh-alert.is-fixed { background: var(--kh-green); }
.kh-alert-ic {
  width: 26px; height: 26px; border-radius: 6px; border: 2px solid #000;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--kh-pink); color: #fff; font: 800 13px/1 var(--kh-font);
}
.kh-alert.is-fixed .kh-alert-ic { background: var(--kh-face); color: #000; }
.kh-alert-st { font: 700 9px/1 var(--kh-mono); text-transform: uppercase; letter-spacing: .1em; }
.kh-alert { opacity: 0; }

/* --- the sweep it runs over everything it holds ---
   A progress bar said "something is being repaired". This says what actually
   happens: it goes LOOKING, catches one record out of everything it holds, and
   puts that one right. The field is small on purpose — one bad cell among
   twenty-seven is a needle, which is the point. */
/* No card of its own. A bordered, shadowed panel inside a bordered, shadowed
   window, holding forty bordered squares, was three card treatments deep — the
   records sit straight on the pane and get the whole width. */
.kh-scan {
  position: relative; overflow: hidden;
  margin-top: 12px;
}
.kh-scan-hd {
  display: flex; align-items: center; gap: 7px; margin-bottom: 9px;
  font: 700 9px/1 var(--kh-mono); text-transform: uppercase; letter-spacing: .11em;
  color: var(--kh-dim); white-space: nowrap;
}
.kh-scan-hd i {
  flex: none; width: 8px; height: 8px; border-radius: 50%;
  border: 1.5px solid #000; background: var(--kh-green);
}
.kh-scan-hd b { font: inherit; color: var(--kh-ink); }
/* howto.js picks the column and row COUNT from the room available and rebuilds
   the cells, so the field always fills the panel rather than being capped into
   a patch in the corner of it */
.kh-grid { display: grid; grid-template-columns: repeat(var(--cols, 12), 1fr); gap: 5px; }
.kh-gcell {
  /* 12, not 16: on a short pane howto.js caps the field so the toast under it
     stays on screen, and a 16px floor quietly refused the cap */
  aspect-ratio: 1; min-height: 12px;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid #000; border-radius: 5px; background: var(--kh-well);
  opacity: calc(.4 + var(--s, 0) * .6);
}
/* a record the sweep has been over and is happy with */
.kh-gcell i { display: block; width: 5px; height: 5px; border-radius: 50%; background: transparent; }
.kh-gcell.is-seen { background: #d8ffe8; }
.kh-gcell.is-seen i { background: rgba(0, 0, 0, .3); }
/* The one it caught. It stays pink underneath the whole time: the repair is a
   pixel flood painted OVER the pink, and then a flat green sheet fading up
   through the pixels. The green is its own LAYER rather than a gradient on the
   cell, because a background-image cannot be faded. */
/* The one it caught: pink, then green floods up through it from the bottom.
   A pixel dissolve at this size came out as a lattice of tiny squares — graph
   paper, not a repair — so this is the plain rise it was before. Overflow, or
   the fill paints square corners over the cell's rounded ones. */
.kh-gcell { position: relative; overflow: hidden; }
.kh-gcell.is-bad {
  background-color: var(--kh-pink);
  background-image: linear-gradient(to top,
    var(--kh-green) var(--f, 0%), transparent var(--f, 0%));
  box-shadow: 0 0 0 3px rgba(247, 0, 135, .5);
}
/* once the repair is most of the way in, the alarm ring goes, and goes softly */
.kh-gcell.is-bad.is-calm { box-shadow: 0 0 0 0 rgba(247, 0, 135, 0); transition: box-shadow .4s ease; }
.kh-gcell.is-bad > i { display: none; }
/* the mark is an element, so it can be STAMPED on rather than switched on */
.kh-gmark { position: relative; z-index: 2; font: 900 11px/1 var(--kh-font); color: #fff; }
.kh-gmark.is-fixed { color: #000; }
/* the leading edge, with its trail behind it */
.kh-beam {
  position: absolute; top: 0; left: 0; width: 64px; height: 0;
  margin-left: -64px; pointer-events: none; opacity: 0;
  background: linear-gradient(to right,
    rgba(0, 237, 113, 0) 0%, rgba(0, 237, 113, .42) 74%,
    rgba(0, 237, 113, .9) 93%, #000 98%, transparent 100%);
}

/* ============================================================
   The end card — a recap and a way back to the top, so it finishes rather
   than just stopping on the last frame.
   ============================================================ */
/* the list and its button sit together in the middle of the stage, rather than
   the list hanging off the top with the button adrift under it */
/* The list and its button sit together in the middle of the stage. On a short
   window (a 768-tall laptop, an SE) six rows and a button are taller than the
   stage, and centring a block that does not fit hides BOTH ends of it — the
   button went under the floor with no way to reach it. So the LIST is the part
   that gives: it shrinks and scrolls inside its own share, and the button is
   pinned under it, always on screen. */
.kh-play-area.is-recap {
  display: flex; flex-direction: column; justify-content: center;
}
.kh-play-area.is-recap .kh-recap {
  flex: 0 1 auto; min-height: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  /* The rows' hard shadows need room inside the scroller — and so does the
     10px each row is translated through on its way in. A transformed
     descendant counts towards the scrollable overflow, so those 10px tipped a
     list that fits into one that does not: the scrollbar appeared for the
     length of the reveal and then went again, taking its width with it and
     jolting the right-hand column. The room is paid for in padding and taken
     straight back in margin, so the travel has somewhere to go and nothing
     below it moves. */
  padding: 2px 5px 16px 0;
  margin-bottom: -12px;
}
.kh-play-area.is-recap .kh-replay { flex: none; }
/* Sized off the WINDOW HEIGHT, not a flat number: the window is min(88vh,860),
   so on a short laptop the stage loses room that six rows never gave back. */
.kh-recap { list-style: none; margin: 0; padding: 0; display: grid; gap: clamp(6px, 1vh, 11px); }
.kh-recap-row {
  /* centred, not baseline: the number is its own box and the description often
     runs to two lines, so a shared baseline hung it off the first one */
  display: grid; grid-template-columns: var(--kh-rn, 22px) auto 1fr; gap: 11px; align-items: center;
  padding: clamp(5px, 1.05vh, 11px) clamp(11px, 1.4vw, 15px);
  border: 2.5px solid #000; border-radius: 10px; background: var(--kh-face);
  box-shadow: 3px 3px 0 0 #000;
}
.kh-recap-row i {
  --kh-rn: clamp(18px, 2.3vh, 22px);
  font-style: normal; width: var(--kh-rn); height: var(--kh-rn); border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid #000; background: var(--nc, var(--kh-green)); color: var(--ni, #000);
  font: 800 11px/1 var(--kh-font);
}
.kh-recap-row b { font: 800 13px/1.3 var(--kh-font); letter-spacing: -.01em; white-space: nowrap; }
.kh-recap-row span { font: 400 12px/1.4 var(--kh-mono); color: var(--kh-dim); }

.kh-replay {
  display: inline-flex; align-items: center; gap: 9px; align-self: center;
  margin-top: clamp(9px, 1.7vh, 20px); cursor: pointer;
  padding: clamp(8px, 1.3vh, 12px) 20px; border: 3px solid #000; border-radius: 11px;
  background: var(--kh-green); box-shadow: 4px 4px 0 0 #000;
  font: 800 12.5px/1 var(--kh-font); text-transform: uppercase; letter-spacing: .05em;
  transition: transform .14s ease, box-shadow .14s ease;
}
.kh-replay svg { width: 15px; height: 15px; display: block; }
.kh-replay:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 0 #000; }
.kh-replay:active { transform: translate(4px, 4px); box-shadow: 0 0 0 0 #000; }
.kh-replay:focus-visible { outline: 3px solid var(--kh-pink); outline-offset: 3px; }
.kh-replay[disabled] { pointer-events: none; }

/* Wide but SHORT (a 720- or 768-tall laptop): six rows down one column do not
   fit, and there is plenty of width going spare — so the list reflows into two
   columns instead of hiding a third of itself behind a scroll. */
@media (min-width: 821px) and (max-height: 930px) {
  .kh-recap { grid-template-columns: 1fr 1fr; gap: clamp(6px, 1vh, 11px) 12px; }
  .kh-recap-row { grid-template-columns: var(--kh-rn, 22px) 1fr; row-gap: 1px; }
  .kh-recap-row span { grid-column: 2; }
}

/* ============================================================
   The transport — play/pause plus a chunky scrub bar with a milestone per
   scene. retro.css's house rules: flat fills, 3px keylines, depth by offset.
   ============================================================ */
.kh-track {
  flex: none; display: grid; grid-template-columns: auto 1fr; gap: clamp(10px, 1.4vw, 16px);
  align-items: center;
  /* vh, so a short window gives the stage back what the transport does not need */
  padding: clamp(7px, 1.2vh, 15px) clamp(16px, 3vw, 34px) clamp(8px, 1.4vh, 17px);
  background: var(--kh-face); border-top: 2.5px solid #000;
}
.kh-play {
  flex: none; width: clamp(34px, 4.8vh, 42px); height: clamp(34px, 4.8vh, 42px); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 3px solid #000; border-radius: 10px; background: var(--kh-green);
  box-shadow: 4px 4px 0 0 #000;
  transition: transform .12s ease, box-shadow .12s ease, background .16s ease;
}
.kh-play:hover { transform: translate(-1px, -1px); box-shadow: 5px 5px 0 0 #000; }
.kh-play:active { transform: translate(4px, 4px); box-shadow: 0 0 0 0 #000; }
.kh-play:focus-visible { outline: 3px solid var(--kh-pink); outline-offset: 3px; }
.kh-play svg { width: 15px; height: 15px; display: block; }
.kh-play .ic-pause { display: none; }
.kh-play[data-state="playing"] { background: var(--kh-yellow); }
.kh-play[data-state="playing"] .ic-pause { display: block; }
.kh-play[data-state="playing"] .ic-play { display: none; }

.kh-rail { position: relative; height: 34px; display: flex; align-items: center; }
.kh-groove {
  position: absolute; left: 0; right: 0; height: 16px;
  border: 2.5px solid #000; border-radius: 4px; background: var(--kh-well);
  overflow: hidden; pointer-events: none;
}
.kh-fill { display: block; height: 100%; width: 0%; background: var(--kh-green); }
/* one notch per scene, sitting in the groove */
.kh-marks { position: absolute; left: 0; right: 0; height: 16px; pointer-events: none; }
.kh-marks i { position: absolute; top: 0; width: 2.5px; height: 100%; background: #000; transform: translateX(-1px); }
/* chunky square thumb — the retro handle, with the same offset shadow */
.kh-thumb {
  position: absolute; top: 50%; left: 0; width: 22px; height: 30px;
  margin: -15px 0 0 -11px; pointer-events: none;
  border: 3px solid #000; border-radius: 5px; background: var(--kh-pink);
  box-shadow: 3px 3px 0 0 #000;
}
.kh-thumb::after {
  content: ""; position: absolute; left: 50%; top: 5px; bottom: 5px; width: 2px;
  margin-left: -1px; background: rgba(0, 0, 0, .45);
}
/* the real control sits on top, invisible: native drag, touch and keyboard */
.kh-range {
  position: relative; z-index: 1; width: 100%; height: 34px; margin: 0;
  -webkit-appearance: none; appearance: none; background: transparent; cursor: grab;
}
.kh-range:active { cursor: grabbing; }
.kh-range::-webkit-slider-runnable-track { height: 34px; background: transparent; }
.kh-range::-moz-range-track { height: 34px; background: transparent; }
.kh-range::-webkit-slider-thumb { -webkit-appearance: none; width: 30px; height: 34px; background: transparent; border: 0; }
.kh-range::-moz-range-thumb { width: 30px; height: 34px; background: transparent; border: 0; }
.kh-range:focus { outline: none; }
.kh-range:focus-visible ~ .kh-thumb { outline: 3px solid var(--kh-pink); outline-offset: 3px; }

/* scene names under the rail, the live one in ink */
/* the row is positioned, not flowed: each label is pinned to its own notch */
.kh-legend { grid-column: 2; position: relative; height: 22px; margin-top: clamp(5px, 1vh, 9px); }
.kh-legend button {
  position: absolute; top: 0; min-width: 0; text-align: left; cursor: pointer;
  display: flex; align-items: center; gap: 7px;
  background: none; border: 0; padding: 0 10px 0 0;
  font: 800 11px/1.3 var(--kh-font); letter-spacing: -.01em;
  color: var(--kh-dim);
  white-space: nowrap;
  transition: color .18s ease;
}
/* the number's LEFT edge sits on the notch. Straddling it meant hanging the
   chip outside the button, where its own overflow sliced it in half. */
/* The underline is PAID FOR IN PADDING AND TAKEN BACK IN MARGIN (stickers.css's
   trick), so the rule paints below the words without adding to the box the flex
   row centres — otherwise the label sat 2-3px above its own number. */
.kh-legend u {
  text-decoration: none;
  padding-bottom: 4px; border-bottom: 2.5px solid transparent;
  margin-bottom: -6.5px;
  overflow: hidden; text-overflow: ellipsis;
}
.kh-legend button[aria-current="true"] u { border-bottom-color: var(--kh-pink); }
/* the step's number in its own colour, so the row reads as five steps */
.kh-legend i, .kh-now i {
  flex: none; font-style: normal;
  width: 19px; height: 19px; border-radius: 5px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid #000; background: var(--nc, var(--kh-green)); color: var(--ni, #000);
  font: 800 10.5px/1 var(--kh-font);
}
.kh-legend button:hover { color: var(--kh-ink); }
.kh-legend button[aria-current="true"] { color: var(--kh-ink); }
.kh-legend button:focus-visible { outline: 2px solid var(--kh-pink); outline-offset: 2px; }
.kh-now { display: none; }

/* ============================================================
   Mobile — the window becomes a sheet rising from the bottom, the transport
   keeps a thumb-sized hit area, and the five scene names collapse to the one
   you are on (five mono labels do not fit 375px and never will).
   ============================================================ */
@media (max-width: 820px) {
  .kos-howto { padding: 0; align-items: flex-end; }
  .kos-howto-win {
    max-width: none; width: 100%; height: 92dvh;
    border-width: 3px 0 0 0; border-radius: 20px 20px 0 0;
    transform: translateY(100%) scale(1);
    transition: transform .34s cubic-bezier(.22, 1, .36, 1), opacity .2s ease;
    transform-origin: 50% 100% !important;   /* beats the inline origin howto.js sets */
  }
  .kos-howto.is-open .kos-howto-win { transform: none; }

  .kh-head { height: var(--kh-headh, 112px); padding: 11px 14px 9px; }
  .kh-head-card {
    padding: 9px 14px; border-width: 2.5px; border-radius: 12px;
    box-shadow: 4px 4px 0 0 #000;
  }
  .kh-h { transform: translateX(-26px); }
  .kh-hand { width: 26px; height: 26px; }
  .kh-play-area { margin: 12px 15px 14px; }
  .kh-scan { margin-top: 10px; }
  .kh-grid { gap: 4px; }
  .kh-beam { width: 46px; margin-left: -46px; }
  /* the status reflows under the name rather than squeezing it to an ellipsis —
     "Timetabling" became "Tim…" when the word sat beside it on a 375px card */
  .kh-sys { grid-template-columns: 22px 1fr; row-gap: 1px; padding: 6px 9px; }
  .kh-sys-ic { width: 22px; height: 22px; }
  .kh-sys-st { grid-column: 2; }
  /* the nav reflows into a scrolling chip row rather than disappearing: it is
     what says the five are sections of ONE system now, which is the point */
  .kh-app-body { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .kh-app-side {
    border-right: 0; border-bottom: 2.5px solid #000;
    display: flex; gap: 5px; align-items: center; padding: 7px 8px;
    overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .kh-app-side::-webkit-scrollbar { display: none; }
  .kh-app-side b, .kh-app-side span { flex: none; white-space: nowrap; }
  .kh-app-side span { border: 2px solid #000; border-radius: 6px; padding: 4px 8px; background: var(--kh-face); }
  .kh-field { grid-template-columns: 78px 1fr; }
  /* six rows and a button have to fit one phone screen, so the row is compact
     rather than the list being cut off at the bottom */
  .kh-recap { gap: 5px; }
  .kh-recap-row {
    /* one declaration: `gap` is the shorthand for BOTH axes, so a `row-gap`
       above it is silently thrown away — which is what made the row 56px and
       pushed the replay button off the bottom of a phone */
    grid-template-columns: 18px 1fr; gap: 1px 8px;
    padding: 6px 10px; border-width: 2px; border-radius: 8px;
  }
  .kh-recap-row i { width: 18px; height: 18px; border-radius: 5px; font-size: 10px; }
  .kh-recap-row b { font: 800 12px/1.25 var(--kh-font); white-space: normal; }
  .kh-recap-row span { grid-column: 2; font-size: 10.5px; line-height: 1.3; }
  .kh-replay {
    width: 100%; justify-content: center;
    margin-top: 12px; padding: 10px 16px; font-size: 11.5px;
  }

  .kh-legend { display: none; }
  .kh-now {
    grid-column: 2; display: flex; align-items: center; gap: 7px; margin-top: 7px;
    font: 800 11.5px/1.3 var(--kh-font); letter-spacing: -.01em; color: var(--kh-ink);
    overflow: hidden; white-space: nowrap;
  }
  .kh-play { width: 46px; height: 46px; }
}

/* body doesn't scroll behind the window (howto.js pins it, keeping scrollY) */
body.kos-howto-lock { position: fixed; inset-inline: 0; width: 100%; overflow: hidden; }
