/* ==========================================================================
   NANOCLAUDE PIPES — [H] THE APPLIANCE PANEL
   Design language: SHRINEWARE, room = APPLIANCE (cross-register furniture).

   THE CONCEPT: the WebGL canvas is this instrument's DISPLAY. Everything in
   this file is the instrument's BODY — a molded light plastic slab mounted
   along the bottom edge of the screen, lit from above, meeting the display
   at a hard bezel. Inside the bezel: shrineware law. Outside it: [F]'s
   digital-lace chrome. The `.ncp-bezel` block below IS the seam and it is
   built to be unmistakable — a dark recessed channel plus a raised molded
   lip, three physical parts you could get a fingernail into.

   Kit primitives (.sw-slab, .sw-key, .sw-well, .sw-lcd, .sw-slider-input,
   .sw-emboss, .sw-deboss, .sw-deboss--dark, .sw-grille) are transcribed
   VERBATIM from ~/.claude/skills/shrineware/shrineware.css §2/§4 so that
   construction physics are the kit's, not hand-rolled. They are themed only
   through their documented custom-property knobs (--sw-slab-fill,
   --sw-key-face/--sw-key-edge/--sw-key-ink, --sw-well-fill, --sw-thumb-at).

   PHYSICS: one light, from above. Raised => inset top highlight + darker
   bottom edge. Recessed => hard top inner shadow + light bottom lip.
   Engraved text => lit bottom lip (.sw-deboss). One linework tone per
   surface. No gradients doing tonal work outside molding, no blur, no
   half-degraded composites.
   ========================================================================== */

#panel,
.ncp-panel {
  /* --- faces (one warm putty plastic; the instrument does not change
         colour when the palette does — only the keycap swatches do) --- */
  --plastic:      #d3cec0;
  --plastic-line: #8b8778;          /* THE linework tone for the body      */
  --bezel-dark:   #24241f;
  --ink:          #3a372e;
  --ink-soft:     #6d6959;
  --hard-blue:    #365ed1;          /* the one structural blue             */

  /* THE HEIGHT BUDGET. This is a control strip along the bottom edge of an
     instrument, not a second page: the display must stay the dominant
     surface at every frame size. 220px total = 21px bezel + 199px body. */
  /* 232px = 21px bezel + 211px body. 220 clipped the foot's legal line by 9px;
     this is the smallest value that shows the whole deck. Still under a fifth of
     a 1200px-tall frame, so the display stays the dominant surface.

     v3 added FOUR controls (crew slider, where-you-stand, its-readouts, the
     sight) and the cap did NOT move. The room came from re-laying the deck,
     not from raising the budget:
       - the keycap column's lower half went from one stacked cap row to THREE
         cap groups side by side (.ncp-subrow) — three controls for 0px;
       - the two action caps moved out of the dials column into the keycap
         column, which freed the dials column's 3rd slider slot;
       - the action caps' min-height dropped 32 -> 17 (the alarm cap governs
         the row, so it never needed to hold two lines pre-emptively);
       - 1px each off .sw-lcd's top/bottom padding, .ncp-label's margin and
         .ncp-strip's margin paid for the sight's row under the readout.
     Deck budget: 232 - 21 bezel - 16 body padding - ~26 foot = ~169px.
     Tallest column after the re-lay is the keycap column at ~167px; before
     v3 the tallest was the dials column at ~171px. It got shorter. */
  --ncp-h:        232px;
  --ncp-bezel-h:  21px;

  --sw-font-mono:  ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --sw-font-serif: Georgia, "Times New Roman", serif;
  --sw-font-hand:  "Bradley Hand", "Segoe Print", "Comic Sans MS", cursive;

  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  max-height: var(--ncp-h);
  visibility: hidden;
  transform: translateY(100%);
  /* Machine timing: stepped, linear, short. No spring, no ease-in-out. */
  transition: transform 180ms steps(6, end), visibility 0s linear 180ms;
  pointer-events: auto;
  color: var(--ink);
  font-family: var(--sw-font-mono);
  -webkit-font-smoothing: antialiased;
}

#panel.is-open,
.ncp-panel.is-open {
  visibility: visible;
  transform: translateY(0);
  transition: transform 180ms steps(6, end), visibility 0s linear 0s;
}

@media (prefers-reduced-motion: reduce) {
  #panel,
  .ncp-panel { transition: visibility 0s; }
}

/* ==========================================================================
   THE SEAM — where the display ends and the appliance begins.
   Three stacked parts, top to bottom:
     1. .ncp-bezel::before  a 3px near-black CHANNEL (the gap the display
        glass sits in — reads as absence of material),
     2. .ncp-bezel          the raised molded LIP: dark plastic, lit hairline
        along its top edge, occlusion under it,
     3. .ncp-body           the light plastic face of the slab.
   Nothing crosses this line. Digital-lace above, shrineware below.
   ========================================================================== */
.ncp-bezel {
  position: relative;
  height: var(--ncp-bezel-h);
  box-sizing: border-box;
  flex: 0 0 auto;
  background: linear-gradient(180deg, #3c3b34 0, var(--bezel-dark) 42%, #17170f 100%);
  border-top: 1px solid #6f6d60;          /* the lit edge of the molding    */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),   /* specular on the top ridge */
    inset 0 -2px 0 rgba(0, 0, 0, 0.45);        /* occlusion under the lip   */
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 18px;
}

/* the dark channel above the lip: a real gap, not a shadow */
.ncp-bezel::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -4px;
  height: 4px;
  background: #0b0b08;
}

/* Self-branding, engraved dark-on-dark into the bezel (kit .sw-deboss--dark
   supplies the ink; light still from above). */
.ncp-bezel-mark {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.30);
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.7);
}

.ncp-bezel-led {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #d77757;
  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.4), 0 0 5px rgba(215, 119, 87, 0.85);
  margin-right: 9px;
  vertical-align: -1px;
}

/* ==========================================================================
   THE SLAB — kit .sw-slab, verbatim construction, themed via --sw-slab-fill.
   Bottom corners squared because the part runs off the bottom of the frame.
   ========================================================================== */
.sw-slab {
  --sw-slab-fill: #bfcbeb;
  --sw-slab-line: color-mix(in srgb, var(--sw-slab-fill) 66%, #000);
  --sw-slab-r: 26px;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--sw-slab-fill) 55%, #fff) 0,
    var(--sw-slab-fill) 14%,
    var(--sw-slab-fill) 82%,
    color-mix(in srgb, var(--sw-slab-fill) 88%, #000) 100%);
  border: 1px solid var(--sw-slab-line);
  border-radius: var(--sw-slab-r);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.75),
    inset 0 -2px 0 rgba(15, 15, 35, 0.16),
    0 5px 14px rgba(15, 18, 38, 0.22);
}

.ncp-body {
  --sw-slab-fill: var(--plastic);
  --sw-slab-line: var(--plastic-line);
  --sw-slab-r: 0px;
  border-top: 0;
  border-left: 0;
  border-right: 0;
  padding: 8px 22px;
  /* The deck is laid out to come in under this; the cap is the guarantee,
     not the mechanism. If a font metric runs long the strip scrolls rather
     than growing up into the display.
     border-box is load-bearing: under content-box the 8px vertical padding is
     added ON TOP of max-height, so the slab measured 215px against a 199px cap
     and the foot hung 17px below the panel box. */
  box-sizing: border-box;
  max-height: calc(var(--ncp-h) - var(--ncp-bezel-h));
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Fixed track count, explicit widths, every child min-width:0 — nothing here
   can push a neighbour or overlap it, at any viewport. */
.ncp-deck {
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr) 236px 250px;
  align-items: start;
  gap: 0 20px;
  max-width: 1560px;
  margin: 0 auto;
}

.ncp-col { position: relative; min-width: 0; }

/* --------------------------------------------------------------------------
   THE SUB-ROW (v3). The deck gained four controls and could not gain a pixel
   of height, so the keycap column's lower half was re-laid from ONE stacked
   cap row into THREE cap groups side by side. Cost: 0px of height.

   Same containment law as the deck itself — a fixed track count, every child
   min-width:0, every cap in an equal 1fr track with `overflow:hidden` and
   `text-overflow:ellipsis`. A face can only ever CLIP; it can never grow into
   its neighbour and it can never sit on top of one. Track ratio is sized to
   the widest face in each group (HALFTONE / INSIDE / HUSH).
   -------------------------------------------------------------------------- */
.ncp-subrow {
  display: grid;
  grid-template-columns: minmax(0, 1.72fr) minmax(0, 1fr) minmax(0, 0.62fr);
  align-items: start;
  gap: 0 10px;
}
.ncp-group { min-width: 0; }

/* a vertical label printed on the plastic beside each cluster */
.ncp-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 4px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.55);   /* printed, lit lip */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ==========================================================================
   PLAQUE — engraved serif caps, letterpressed into a silver casting.
   ========================================================================== */
.ncp-plaque {
  background: linear-gradient(135deg, #f0f2f5 0%, #e8ebef 15%, #f5f7fa 30%,
    #dde1e4 50%, #e8ebef 70%, #f2f4f7 85%, #dde1e4 100%);
  border: 1.5px solid #b7b7b7;
  border-radius: 6px;
  box-shadow:
    inset 0 2px 4px rgba(255, 255, 255, 0.8),
    inset 0 -1px 1px rgba(0, 0, 0, 0.1),
    0 2px 5px rgba(0, 0, 0, 0.16);
  padding: 5px 12px 6px;
  text-align: center;
}

.ncp-plaque-text {
  display: block;
  font-family: var(--sw-font-serif);
  font-size: 17px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: #6a6f78;
  text-shadow:
    0 -1px 0 #fff,
    0 1px 0 rgba(0, 0, 0, 0.6),
    -1px 0 0 rgba(255, 255, 255, 0.8),
    1px 0 0 rgba(0, 0, 0, 0.4),
    0 2px 4px rgba(0, 0, 0, 0.3);
}

.ncp-plaque-sub {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #8a8f98;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.9);
}

/* bureaucratic-collectible: the serial, struck into the plastic */
.ncp-serial {
  margin: 5px 0 0;
  font-size: 13px;
  letter-spacing: 0.08em;
  white-space: nowrap;
  color: var(--ink-soft);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.55);
}
.ncp-serial b { font-weight: 700; color: var(--ink); }

/* ==========================================================================
   THE HAND — inline SVG at structural scale + ballpoint margin annotations.
   No filters; the wobble is in the path data.
   ========================================================================== */
/* The diagram is drawn at 236x122 user units and mounted smaller than that:
   it is a margin sketch on the body, and the height budget is the reason. */
.ncp-fig {
  display: block;
  width: 168px;
  height: 83px;
  margin: 4px 0 0 -4px;
  overflow: visible;
}
.ncp-fig .hand-stroke {
  fill: none;
  stroke: var(--hard-blue);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.82;
}
.ncp-fig .hand-text {
  fill: var(--hard-blue);
  font-family: var(--sw-font-hand);
  font-size: 12.5px;               /* user units — ~8.9px on the mounted size */
  opacity: 0.9;
}

.ncp-anno {
  position: absolute;
  font-family: var(--sw-font-hand);
  font-size: 13px;
  line-height: 1.15;
  color: var(--hard-blue);
  opacity: 0.85;
  pointer-events: none;
  white-space: nowrap;
}
/* Both annotations hang off the RIGHT edge of their column, clear of the
   printed label at its left edge — they cannot land on top of it. */
.ncp-anno--pitch { top: -4px; right: 2px; left: auto; transform: rotate(-3deg); }
.ncp-anno--keys  { top: -4px; right: 2px; left: auto; transform: rotate(2deg); }
.ncp-anno svg { display: block; overflow: visible; }
/* arrow and words on ONE line, so the annotation is a 15px band that sits
   entirely above the label row instead of reaching down into the keycaps */
.ncp-anno--keys { display: flex; align-items: center; gap: 5px; }
.ncp-anno--keys svg { flex: 0 0 auto; }
.ncp-anno .hand-stroke {
  fill: none;
  stroke: var(--hard-blue);
  stroke-width: 1.4;
  stroke-linecap: round;
  opacity: 0.8;
}

/* ==========================================================================
   KEYCAPS — kit .sw-key, verbatim. Travel lives in the bottom edge.
   ========================================================================== */
.sw-key {
  --sw-key-face: #f2ecd9;
  --sw-key-edge: color-mix(in srgb, var(--sw-key-face) 62%, #000);
  --sw-key-ink: #6c6142;
  --sw-key-travel: 7px;
  --sw-key-r: 9px;
  display: inline-block;
  padding: 10px 16px;
  border: 0;
  border-radius: var(--sw-key-r);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--sw-key-face) 72%, #fff) 0,
    var(--sw-key-face) 42%,
    color-mix(in srgb, var(--sw-key-face) 93%, #000) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.60),
    0 var(--sw-key-travel) 0 var(--sw-key-edge);
  margin-bottom: var(--sw-key-travel);
  color: var(--sw-key-ink);
  font-family: var(--sw-font-mono);
  font-weight: 700;
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-align: center;
  line-height: 1.25;
  cursor: pointer;
  user-select: none;
}
.sw-key:active {
  transform: translateY(calc(var(--sw-key-travel) - 2px));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.60),
    0 2px 0 var(--sw-key-edge);
}
.sw-key:focus-visible {
  outline: 2px solid var(--hard-blue);
  outline-offset: 2px;
}

/* AT THE STOP (v3.5 — zoom already at ±5). The cap is pressed flat into its
   well and has no travel left to give: the shadow is the message, exactly as
   .is-on is. Deliberately NOT an opacity fade — a faded key still looks like
   it would move. Ink is muted only as a second signal, never as the first.
   `transform` rather than a smaller margin so the row height cannot change. */
.sw-key:disabled {
  cursor: default;
  transform: translateY(calc(var(--sw-key-travel) - 1px));
  box-shadow:
    inset 0 2px 3px rgba(0, 0, 0, 0.34),
    0 1px 0 var(--sw-key-edge);
  color: color-mix(in srgb, var(--sw-key-ink) 48%, var(--sw-key-face));
}

/* HELD DOWN (the active palette / active screen). The bottom edge collapses
   to 2px and the top highlight is gone — the cap is sitting in its well. */
.sw-key.is-on {
  transform: translateY(calc(var(--sw-key-travel) - 2px));
  box-shadow:
    inset 0 2px 3px rgba(0, 0, 0, 0.30),
    0 2px 0 var(--sw-key-edge);
}

/* --- palette keycap: a swatch of that palette's signal over its paper --- */
.ncp-keyrow {
  display: flex;
  gap: 5px;
  margin: 0;
  padding: 0;
}

/* ONE row of seven. Fixed track count, equal 1fr tracks that can shrink to
   zero: a cap can never grow into its neighbour, and its face clips.
   .ncp-keyrow--mode also carries the two v3 cap groups (WHERE YOU STAND,
   ITS READOUTS) — same construction, same containment guarantee. */
.ncp-keyrow--pal,
.ncp-keyrow--mode {
  display: grid;
  grid-auto-flow: column;                 /* one row, however many caps      */
  grid-auto-columns: minmax(0, 1fr);      /* equal tracks that can shrink    */
  gap: 0 5px;
  max-width: none;
}

.ncp-key-pal {
  --sw-key-face: #efeade;
  --sw-key-edge: #a49c85;
  --sw-key-ink: var(--ink);
  padding: 6px 5px 5px;
  min-width: 0;
  overflow: hidden;
}

.ncp-swatch {
  display: block;
  height: 20px;
  border: 1px solid rgba(0, 0, 0, 0.42);      /* one linework tone per key */
  border-radius: 2px;
  background: var(--pal-paper, #111);
  box-shadow:
    inset 0 2px 3px rgba(0, 0, 0, 0.35),      /* the swatch sits in a well */
    inset 0 -1px 0 rgba(255, 255, 255, 0.35);
  position: relative;
}
.ncp-swatch::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: var(--pal-signal, #d77757);
}

/* The face is an abbreviation in a track it cannot escape. Full name lives
   in `title` and is spelled out in the READOUT while the key is held down. */
.ncp-key-name {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- small screen-select keycaps --- */
.ncp-key-mode {
  --sw-key-face: #c8c2ae;
  --sw-key-edge: #8b8571;
  --sw-key-ink: #43402f;
  --sw-key-travel: 5px;
  font-size: 11px;
  padding: 8px 4px;
  letter-spacing: 0.04em;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The three v3 framing caps and the two readout caps are .ncp-key-mode with a
   dial-plate face — no new hue enters the appliance, they reuse the screen-tone
   putty. Only the two action caps carry candy colour, as before. */
.ncp-key-frame,
.ncp-key-hud { letter-spacing: 0.06em; }

/* --- action keycaps --- */
.ncp-key-act {
  --sw-key-face: #cde98f;
  --sw-key-edge: #88a44c;
  --sw-key-ink: #55613a;
  --sw-key-travel: 6px;
  font-size: 13px;
  padding: 7px 6px;
  width: 100%;
  min-width: 0;
  /* The copy is the copy — it wraps onto a second legend line rather than
     truncating. The row cannot JUMP on a state flip because the pause cap's
     two faces (HOLD IT STILL / LET IT RUN) are both shorter than the alarm
     cap beside it, and .ncp-actrow stretches: the alarm cap always governs
     the row height, so min-height only needs to hold one legend line. */
  white-space: normal;
  min-height: 17px;
}
.ncp-key-act--alarm {
  --sw-key-face: #e8b05e;
  --sw-key-edge: #3f2d14;
  --sw-key-ink: #6b4d1e;
}

.ncp-keygroup { margin-bottom: 1px; }
.ncp-actrow { display: flex; align-items: stretch; gap: 9px; margin-top: 4px; }
.ncp-actrow > * { flex: 1 1 0; min-width: 0; }

/* ==========================================================================
   THE SIGHT (v3.5) — two detent caps either side of a struck readout chip,
   mounted directly under the LCD strip because the step IS a reading.
   Buttons, not a slider: the steps are counted, and they should feel counted.
   ========================================================================== */
.ncp-sight {
  display: flex;
  /* tops aligned, not centres: the caps' 4px travel hangs BELOW the chip,
     which is where a key's shadow belongs under a light from above */
  align-items: flex-start;
  gap: 6px;
  margin-top: 4px;
  min-width: 0;
}

.ncp-key-mini {
  --sw-key-face: #c8c2ae;
  --sw-key-edge: #8b8571;
  --sw-key-ink: #43402f;
  --sw-key-travel: 4px;
  --sw-key-r: 6px;
  flex: 0 0 auto;
  width: 32px;
  padding: 3px 0;
  font-size: 14px;
  line-height: 1;
}

/* the chip is the sliders' own readout surface, reused verbatim so the step
   reads as a measured value and not as a caption */
.ncp-zoomval {
  flex: 1 1 auto;
  min-width: 0;
  text-align: center;
  white-space: pre;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ==========================================================================
   SLIDERS — kit ribbed slot + ribbed thumb, verbatim.
   ========================================================================== */
.ncp-slider-block { margin-bottom: 3px; }

.ncp-slider-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 3px;
}
.ncp-slider-head span:first-child {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.55);
}
.ncp-slider-val {
  flex: 0 0 auto;
  font-size: 13px;
  font-weight: 700;
  font-style: italic;
  letter-spacing: 0.1em;
  color: #2c3a2c;
  background: linear-gradient(180deg, #9fae94, #b3bfa6);
  border: 1px solid rgba(20, 25, 15, 0.3);
  border-radius: 3px;
  padding: 1px 6px;
  box-shadow:
    inset 0 2px 3px rgba(18, 22, 12, 0.34),
    inset 0 -1px 0 rgba(255, 255, 255, 0.45);
}

input[type="range"].sw-slider-input {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 22px;
  padding: 0 3px;
  background: linear-gradient(180deg, #23252c, #3a3d47 60%);
  border: 0;
  border-radius: 12px;
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.55),
    inset 0 -1px 0 rgba(255, 255, 255, 0.28);
  cursor: ew-resize;
}
input[type="range"].sw-slider-input::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 38px;
  height: 17px;
  border: 0;
  border-radius: 6px;
  background: repeating-linear-gradient(90deg,
    #ffffff 0 2px, #c3c6cd 2px 3px, #f2f3f5 3px 4px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    inset 0 -1px 0 rgba(0, 0, 0, 0.20),
    0 2px 4px rgba(0, 0, 0, 0.45);
}
input[type="range"].sw-slider-input::-moz-range-thumb {
  width: 38px;
  height: 17px;
  border: 0;
  border-radius: 6px;
  background: repeating-linear-gradient(90deg,
    #ffffff 0 2px, #c3c6cd 2px 3px, #f2f3f5 3px 4px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    inset 0 -1px 0 rgba(0, 0, 0, 0.20),
    0 2px 4px rgba(0, 0, 0, 0.45);
}
input[type="range"].sw-slider-input:focus-visible {
  outline: 2px solid var(--hard-blue);
  outline-offset: 2px;
}

/* ==========================================================================
   LCD WELL — kit .sw-well recess holding a .sw-lcd glass panel.
   Ghost 88:88:88 layer required, sits BEHIND the live digits, same metrics.
   ========================================================================== */
.sw-well {
  --sw-well-fill: #aeb9d8;
  --sw-well-r: 14px;
  background: var(--sw-well-fill);
  border: 1px solid rgba(20, 25, 45, 0.18);
  border-radius: var(--sw-well-r);
  box-shadow:
    inset 0 2px 3px rgba(18, 22, 40, 0.35),
    inset 0 8px 12px -6px rgba(18, 22, 40, 0.28),
    inset 0 -1px 0 rgba(255, 255, 255, 0.50);
}

.ncp-well {
  --sw-well-fill: #b5b1a2;
  --sw-well-r: 10px;
  padding: 6px;
}

.sw-lcd {
  background: linear-gradient(180deg, #3f4a42, #4a554b);
  color: #cfe0cf;
  font-family: var(--sw-font-mono);
  font-weight: 700;
  font-style: italic;
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  line-height: 1.4;
  /* was 7/8 — one pixel off each end, which is what bought the sight its row
     under the strip without touching the height cap */
  padding: 6px 10px 7px;
  border-radius: 5px;
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.5),
    inset 0 -1px 0 rgba(255, 255, 255, 0.14);
}

.ncp-lcd-line {
  position: relative;
  display: block;
  white-space: pre;
}
/* the numeral field: ghost segments sit behind the live digits, same metrics */
.ncp-num {
  position: relative;
  display: inline-block;
}
.ncp-lcd-ghost {
  position: absolute;
  left: 0;
  top: 0;
  color: #cfe0cf;
  opacity: 0.1;
  pointer-events: none;
}
.ncp-lcd-live { position: relative; }
.ncp-lcd-line--sm { font-size: 13px; letter-spacing: 0.12em; }

/* The keycap face is abbreviated; this line is where the active signal set is
   spelled out in full. It clips rather than wrapping the LCD to a 5th line. */
.ncp-lcd-line--set {
  letter-spacing: 0.04em;
  white-space: pre;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* the printed strip under the well */
.ncp-strip {
  margin: 4px 0 0;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.55);
  /* wraps to a second line rather than truncating a count — it is data */
}

/* ==========================================================================
   THE FOOT — the printed legal line along the bottom edge of the body.
   A single score line across the whole slab: dark groove (the body's ONE
   linework tone) with its lower lip catching the light from above.
   ========================================================================== */
.ncp-foot {
  max-width: 1560px;
  margin: 4px auto 0;
  padding-top: 3px;
  border-top: 1px solid var(--plastic-line);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55);
}

/* the uncanny note. Printed like every other legal line on the body. */
.ncp-note {
  margin: 0;
  font-size: 13px;
  line-height: 1.35;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
  max-width: none;
}

/* ==========================================================================
   Narrow frames: the appliance keeps its parts, it just gets shorter.
   ========================================================================== */
/* v3: the keycap column now carries three cap groups on its lower row, so it
   needs ~530px of track before anything starts clipping. The fixed columns
   hand width back to it well before the margin sketch has to go. */
@media (max-width: 1360px) {
  .ncp-body { padding: 8px 16px; }
  .ncp-deck {
    grid-template-columns: 200px minmax(0, 1fr) 214px 222px;
    gap: 0 16px;
  }
  .ncp-subrow { gap: 0 8px; }
}

/* Below this the margin sketch and the ballpoint annotations are the first
   things to go: they are the parts that need width they no longer have. */
@media (max-width: 1180px) {
  .ncp-body { padding: 8px 14px; }
  .ncp-deck {
    grid-template-columns: 184px minmax(0, 1fr) 206px 212px;
    gap: 0 14px;
  }
  .ncp-col--ident .ncp-fig { display: none; }
  .ncp-anno { display: none; }
  .ncp-plaque { padding: 5px 8px 6px; }
  .ncp-plaque-text { font-size: 15px; }
  /* the cap faces start paying for the third group here rather than at 1020,
     so HALFTONE survives as a whole word for another 160px of viewport */
  .ncp-key-mode { padding: 8px 3px; letter-spacing: 0; }
  .ncp-key-frame, .ncp-key-hud { letter-spacing: 0; }
}

/* Tighter still: the keycap faces give up their letter-spacing and padding
   before they give up being seven in a row. */
@media (max-width: 1020px) {
  .ncp-key-pal { padding: 6px 2px 5px; }
  .ncp-key-name { letter-spacing: 0; }
  .ncp-keyrow--pal, .ncp-keyrow--mode { gap: 0 4px; }
  .ncp-subrow { gap: 0 6px; }
  /* the action legends stop wrapping and start clipping: a second legend line
     here would push the deck past the height cap, and the cap is the law */
  .ncp-key-act {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: 0;
  }
  .ncp-sight { gap: 4px; }
  .ncp-key-mini { width: 28px; }
}

/* Narrow frames: the appliance keeps every part, it just stacks. The deck
   becomes two columns and the body scrolls inside its cap — the slab must
   never grow up into the display it is mounted under. */
@media (max-width: 900px) {
  .ncp-deck {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 10px 16px;
  }
  .ncp-col--keys { grid-column: 1 / -1; }
}

/* Short frames: shrink the whole budget, do not just clip it. */
@media (max-height: 620px) {
  #panel, .ncp-panel { --ncp-h: 188px; }
}
