/* THE VIRTUAL TRAINING ROOM. Foundation tokens only. */
/* ⛔ minmax(0,1fr), not 1fr. The stage is width:100% with an aspect-ratio,
   so a bare 1fr track resolves against its own content and collapses the
   column to min-content — the stage came out 30px wide and every piece
   sat at the minimum size. minmax(0,...) breaks the circular reference. */
/* ⛔ 6 Oct · FULL BLEED, LIBRARY ALONG THE BOTTOM. Nathan: "I need the width
   of that picture to stretch the page, put all the instruments on the bottom
   and that will free up the left side of the page." The room now takes the
   whole viewport width; the catalogue is a scrolling strip underneath it. */
.rm { display:block; width:100vw; position:relative; left:50%;
      transform:translateX(-50%); max-width:none; }
.rm__main { min-width:0; }
.rm__lib {
  background:var(--bg-card); border-top:1px solid var(--rule);
  border-bottom:1px solid var(--rule); padding:8px 14px;
  display:flex; gap:16px; overflow-x:auto; align-items:flex-start;
}
.rm__libgroup { flex:0 0 auto; }
.rm__libh {
  font-family:'Courier New',monospace; font-size:8.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--bronze-deep); margin:14px 0 8px;
}
.rm__libh:first-child { margin-top:0; }
.rm__grid { display:flex; gap:5px; }
.rm__item {
  width:62px; flex:0 0 62px;
  background:var(--bg-soft); border:1px solid var(--rule); border-radius:4px;
  padding:4px 3px 5px; cursor:grab; text-align:center; font-size:8px;
  line-height:1.12; color:var(--ink-soft);
}
.rm__item:hover { border-color:var(--bronze); background:var(--bg-card); }
.rm__item img { width:100%; aspect-ratio:1; object-fit:contain; display:block; margin-bottom:4px; }
.rm__item b { display:block; color:var(--ink); font-weight:600; font-size:8.5px; }

.rm__main { min-width:0; }
.rm__bar { display:flex; gap:9px; flex-wrap:wrap; align-items:center; margin-bottom:12px; }
.rm__btn {
  font-family:'Courier New',monospace; font-size:10.5px; letter-spacing:.14em;
  text-transform:uppercase; cursor:pointer; padding:9px 15px; border-radius:4px;
  background:var(--bg-card); color:var(--ink); border:1px solid var(--rule);
}
.rm__btn:hover { border-color:var(--bronze); background:var(--bg-soft); }
.rm__btn.on { background:var(--bronze); color:var(--bg-card); border-color:var(--bronze); }
.rm__btn--go { background:var(--bronze); color:var(--bg-card); border-color:var(--bronze); }
.rm__dim {
  font-family:'Courier New',monospace; font-size:10.5px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink-soft); display:flex; align-items:center; gap:6px;
}
.rm__dim input {
  width:56px; padding:7px 8px; font:inherit; text-align:center; color:var(--ink);
  background:var(--bg-card); border:1px solid var(--rule); border-radius:4px;
}
.rm__count { margin-left:auto; font-family:'Courier New',monospace; font-size:11px; color:var(--ink-soft); }

/* ⛔ 6 Oct · A WOODEN STAGE, AND THE HOUSE BEHIND IT. Nathan: "I want the stage
   to have a wooden floor, which also introduces carpets... Most stages are
   usually wood or risers that are built up, which still require a drum rug."
   The floor is drawn in CSS — repeating board lines — so there is no image to
   load and it stays crisp at any size. The lower strip is the house, where the
   tech table lives, so the two zones are visibly different places. */
.rm__stage {
  position:relative; aspect-ratio:1600/1062; border:1px solid var(--rule);
  border-radius:6px; overflow:hidden; touch-action:none;
  background:#241c14 center/cover no-repeat;
  background-image:url('/room-bg/venue-hall.jpg');
}
/* ⛔ THIS IS THE ACTUAL BUILDING. 851 Broadway, looking from the back of the
   hall toward the stage end. Exposed timber, string lights, brick, the grey
   freight doors, the plank floor. Nathan pulled these off the web in three
   minutes while I was explaining why it was hard. */





.rm__ghost {
  position:fixed; transform:translate(-50%,-50%); pointer-events:none;
  opacity:.75; z-index:9999; border-radius:4px;
  box-shadow:0 8px 22px rgba(26,35,50,.28);
}
.rm__zone {
  font-family:'Courier New',monospace; font-size:7px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--muted); display:block; margin-top:2px;
}
.rm__item.wrongzone { outline:2px solid #9A5A45; }

/* ⛔ THE ACTUAL BUILDING. 851 Broadway, photographed from the entrance steps
   looking down the hall toward the stage end. Exposed timber, string lights,
   brick, the grey freight doors, the plank floor.
   Layout, from Nathan who works in it:
     · the stage covers the door at the far end of this view
     · the band sets 4–5 ft off that back wall so the emergency door stays clear
     · the storage room for chairs and tables is off to the right
     · the outlets are IN THE FLOOR — positions to be marked
   (This rule was accidentally deleted by a regex on 6 Oct and the stage
    collapsed to 30px. Keep it whole.) */
.rm__stage {
  position:relative; width:100%; height:78vh; min-height:420px;
  border:1px solid var(--rule); border-radius:6px; overflow:hidden;
  touch-action:none; background:#241c14; cursor:grab;
}
/* ⛔ you must never have to guess which mode you are in. In Wire mode the
   whole room says so and the cursor changes. */
.rm__stage.wiring { cursor:crosshair; box-shadow:inset 0 0 0 3px var(--bronze); }
.rm__stage.wiring::after {
  content:'WIRE MODE - CLICK A SOURCE, THEN CLICK WHERE IT GOES. THE GRIPS STILL WORK.';
  position:absolute; left:0; right:0; top:0; padding:5px 0; text-align:center;
  font-family:'Courier New',monospace; font-size:9.5px; letter-spacing:.2em;
  color:#2A1E10; background:var(--bronze-glow); z-index:6; pointer-events:none;
}
/* ⛔ THE ROOM, NOT A PICTURE OF IT. Six generated venues laid
   end to end as one continuous space you drag through. Segment 1 looks at the
   stage end and is where the work happens; the rest is the room around you, so
   a student can see what they are standing in. */
/* ⛔ A CYLINDER, NOT A STRIP. Nathan: "I can't even get a full scroll on the
   panorama." A strip has two ends and you hit them. The four views are laid out
   TWICE and the pan wraps modulo four, so the room turns forever in either
   direction and never stops. */
.rm__strip {
  position:absolute; inset:0; display:block; transform:none !important;
}
.rm__view { position:absolute; inset:0; }
/* ⛔ 5 · VENUE-NEUTRAL. Nathan: "I need them training on a platform where it
   doesn't matter what the venue looks like or where the power is." Six rooms
   were generated for exactly that and the single real venue was dropped on
   6 Oct — "drop the Depot, use the six". Blank is still a real option, and the
   list comes from the venue manifest so a seventh needs no code. */
.rm__stage.bare .rm__view img { display:none; }
.rm__stage.bare {
  background:
    repeating-linear-gradient(90deg, rgba(122,90,40,.13) 0 1px, transparent 1px 5%),
    repeating-linear-gradient(0deg,  rgba(122,90,40,.09) 0 1px, transparent 1px 8%),
    linear-gradient(180deg,#E6DBC6 0%,#DCCFB4 60%,#CBBB9E 60.2%,#C2B193 100%);
}
.rm__stage.bare::before {
  content:'STAGE'; position:absolute; left:12px; top:9px;
  font-family:'Courier New',monospace; font-size:9px; letter-spacing:.26em;
  color:var(--bronze-deep); opacity:.8;
}
.rm__stage.bare::after {
  content:'THE HOUSE - AUDIENCE THIS WAY'; position:absolute; left:0; right:0; bottom:7px;
  text-align:center; font-family:'Courier New',monospace; font-size:9px;
  letter-spacing:.22em; color:var(--bronze-deep); opacity:.8;
}
/* soften the joins so the room reads as continuous rather than chopped */


.rm__view img { width:100%; height:100%; object-fit:cover; display:block; pointer-events:none; user-select:none; -webkit-user-drag:none; }
/* ⛔ the panorama IS the stage. One surface you turn AND place on. */
.rm__pano { width:100%; height:100%; display:block; cursor:grab; touch-action:none; }
.rm__pano:active { cursor:grabbing; }
.rm__stage.bare .rm__pano { display:none; }
.rm__turn { position:absolute; left:10px; top:10px; z-index:4; pointer-events:none;
  font-family:'Courier New',monospace; font-size:9px; letter-spacing:.12em;
  color:rgba(255,236,210,.78); background:rgba(0,0,0,.42);
  padding:.18rem .55rem; border-radius:20px; }





/* ⛔ THE BAND LINE IS GONE. It was drawn at a fixed 46% down a FLAT stage
   photograph, where it marked the back wall. The venues are 360 panoramas now,
   so that same line lands across the middle of every room — through the
   altar of a church, across a gymnasium floor — marking nothing.
   Nathan, 6 Oct: "Why is there a band line in the middle of every picture."
   The rule it carried (set up 4–5 ft off the back wall, keep the emergency
   door clear) is taught in the module text and in the stage zoom copy, which
   is where it belongs: an instruction, not a line painted over a photograph of
   a room it does not fit. */
.rm__wires { position:absolute; inset:0; pointer-events:none; }
.rm__p {
  position:absolute; transform:translate(-50%,-50%); cursor:grab;
  text-align:center; user-select:none;
}
.rm__p img { width:100%; display:block; pointer-events:none; }
.rm__p img { filter:drop-shadow(0 6px 10px rgba(0,0,0,.45)); }
/* ⛔ THE SELECTED PIECE RISES. Two pieces that overlap meant the one underneath
   had a grip buried under the one on top — selected, visible, and that one grip
   simply would not take a click. Whatever you are working on sits above
   everything else, which is what makes its grips reachable. */
.rm__p.sel { z-index:5; }
.rm__p.sel img { filter:drop-shadow(0 0 0 var(--bronze)) drop-shadow(0 0 6px var(--bronze)) drop-shadow(0 6px 10px rgba(0,0,0,.45)); }
.rm__p.wire { outline:2px dashed var(--bronze-deep); outline-offset:3px; }
/* ⛔ 6 Oct · Nathan put two drum kits down and could only fix it by clearing
   the whole stage. One piece, one delete. The keyboard Delete key still works,
   but a control you cannot see is a control that does not exist. */
/* ⛔ 6 Oct · a resize grip. Perspective scaling gets a piece close, but only
   the person placing it knows how far back it really sits. Nathan: "The drums
   need to be all the way back against the door, for this I need depth
   perception to place it where I want it." */
/* ⛔⛔⛔ 6 Oct · A CONTROL HAS TO LOOK LIKE A CONTROL. These were 18px pale
   squares with no icon, sitting on the corners of a box the student could not
   see — and because a photographed instrument has transparent space around it,
   they floated out in the middle of a window several feet from the drums.
   Nathan: "I have no functionality when it comes to the instruments unless I
   want to delete them. That's the only thing that works." Delete was the only
   one that worked because the red circle with an × was the only one that READ
   as a button. The other three looked like scenery.
   So: a frame that shows the box the handles belong to, handles at 26px with
   a glyph and a ring that holds up over a bright window or a dark floor, and
   the piece's name on a chip underneath so you know what is selected. */
.rm__p.sel::before {
  content:''; position:absolute; inset:-2px; pointer-events:none;
  border:2px dashed var(--bronze); border-radius:5px;
  box-shadow:0 0 0 2px rgba(0,0,0,.35), inset 0 0 0 2px rgba(0,0,0,.35);
}
.rm__p.sel::after {
  content:attr(title); position:absolute; left:50%; bottom:-26px;
  transform:translateX(-50%); pointer-events:none; white-space:nowrap;
  background:rgba(24,18,12,.85); color:#FFF8EC; border-radius:4px;
  padding:2px 8px; font:600 11px/15px 'Segoe UI',sans-serif; letter-spacing:.04em;
}
.rm__rot, .rm__siz, .rm__tlt, .rm__del {
  position:absolute; width:26px; height:26px; border-radius:50%;
  border:2px solid #FFF8EC; box-shadow:0 1px 4px rgba(0,0,0,.6);
  font:700 14px/22px 'Segoe UI Symbol','Segoe UI',sans-serif; font-style:normal;
  color:#FFF8EC; text-align:center; z-index:6; transition:transform .08s;
}
.rm__rot:hover, .rm__siz:hover, .rm__tlt:hover, .rm__del:hover { transform:scale(1.18); }
/* ⛔⛔ GRIPS SIT INSIDE THE PIECE, not hanging off it. They used to be at
   -9px on every side, so the moment a piece drifted toward the edge of the
   stage — which happens the instant you turn the room — the grips crossed the
   boundary and were clipped away. The piece was still half visible and still
   looked selected, but nothing could be grabbed. Inside the box, they are
   reachable whenever any part of the piece is. */
.rm__tlt { left:2px; bottom:2px; background:#2E4A3C; cursor:ns-resize; }
.rm__tlt::after { content:'\21D5'; }
.rm__siz { right:2px; bottom:2px; background:#1F3A52; cursor:nwse-resize; }
.rm__siz::after { content:'\2922'; }
.rm__del { left:2px; top:2px; background:#8C2F1E; cursor:pointer; }
.rm__rot { right:2px; top:2px; background:#8A6A32; cursor:grab; }
.rm__rot::after { content:'\21BB'; }
/* ⛔ the two places the work actually happens, enlarged. Nathan: "since I
   can't have panoramic, we will have to have zoom in shots where we can work so
   the students can see what's going on." */
.rm__zooms {
  display:grid; grid-template-columns:1fr 1fr; gap:18px;
  width:96vw; max-width:1800px; margin:22px auto 0;
}
.rm__zoom h3 { font-family:Georgia,serif; font-size:21px; color:var(--ink); margin:0 0 6px; }
.rm__zoom p { font-size:14px; line-height:1.6; color:var(--ink-soft); margin:0 0 10px; }
.rm__zstage.wiring { cursor:crosshair; box-shadow:inset 0 0 0 3px var(--bronze); }
/* ⛔ THESE TWO ARE REAL PLACEMENT SURFACES, not decoration — room.js
   registers them as zones and toggles them in wire mode. They used to take
   their HEIGHT from the Depot photograph inside them, so when that photo was
   retired on 6 Oct the box collapsed to a thin dark bar and looked broken.
   A zone you can drop gear onto has to look like a surface, so it is DRAWN
   rather than photographed: boards for the stage, a dark tabletop for front of
   house. That also makes it venue-neutral — it is any stage, not one. */
.rm__zstage {
  position:relative; border:1px solid var(--rule); border-radius:6px;
  overflow:hidden; touch-action:none; min-height:250px;
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,.20) 0 2px, transparent 2px 7.5%),
    linear-gradient(175deg, #6b4a2a 0%, #8a6038 42%, #5e4024 100%);
}
.rm__zstage::after {
  content:'THE STAGE 4 DROP GEAR HERE';
  position:absolute; left:10px; bottom:8px; font-family:'Courier New',monospace;
  font-size:8.5px; letter-spacing:.14em; color:rgba(255,232,200,.45);
  pointer-events:none;
}
.rm__zstage--top {
  background:
    repeating-linear-gradient(0deg, rgba(255,255,255,.035) 0 1px, transparent 1px 9%),
    linear-gradient(170deg, #35302a 0%, #262220 60%, #1c1917 100%);
}
.rm__zstage--top::after { content:'THE TECH TABLE 4 LOOKING DOWN'; }
.rm__zstage img { width:100%; display:block; }
.rm__zstage .rm__p img { filter:drop-shadow(0 6px 10px rgba(0,0,0,.5)); }
@media (max-width:980px){ .rm__zooms { grid-template-columns:1fr; } }
.rm__note {
  margin-top:12px; padding:13px 16px; border-radius:5px; font-size:14px; line-height:1.6;
  background:var(--bg-soft); border-left:3px solid var(--bronze); color:var(--ink-soft);
}
.rm__note.bad   { border-left-color:#9A5A45; background:#F6ECE8; color:#5A2A1C; }
.rm__note.fatal { border-left-color:#8C2F1E; background:#F3E2DD; color:#5A1A0E; }
.rm__note.ok    { border-left-color:#4F7A43; background:#EDF3EA; color:#24401D; }

.rm__brief { margin-bottom:16px; }
.rm__brief p.q {
  font-family:Georgia,serif; font-style:italic; font-size:17px; line-height:1.65;
  color:var(--ink); margin:0 0 10px; padding-left:16px; border-left:3px solid var(--bronze);
}
.rm__brief ul { margin:0; padding-left:18px; font-size:14px; line-height:1.7; color:var(--ink-soft); }

.rm__res { margin-top:16px; }
.rm__res__row {
  display:grid; grid-template-columns:26px 1fr; gap:11px; padding:9px 13px;
  margin-bottom:6px; border-radius:4px; font-size:14px;
  background:var(--bg-card); border:1px solid var(--rule); color:var(--ink-soft);
}
.rm__res__row.y { border-left:3px solid #4F7A43; }
.rm__res__row.n { border-left:3px solid #9A5A45; }
.rm__res__row b { color:var(--ink); }
.rm__score {
  font-family:Georgia,serif; font-size:28px; color:var(--ink); margin:0 0 10px;
  font-variant-numeric:tabular-nums;
}

@media (max-width:860px){
  .rm { grid-template-columns:1fr; width:100%; left:0; transform:none; }
  .rm__lib { position:static; height:auto; max-height:220px; }
  .rm__grid { grid-template-columns:repeat(4,1fr); }
  .rm__stage { height:60vh; }
}
@media print {
  .top,.corner-mark,footer,.rm__lib,.rm__bar,.rm__brief,/* ⛔ the two places the work actually happens, enlarged. Nathan: "since I
   can't have panoramic, we will have to have zoom in shots where we can work so
   the students can see what's going on." */
.rm__zooms {
  display:grid; grid-template-columns:1fr 1fr; gap:18px;
  width:96vw; max-width:1800px; margin:22px auto 0;
}
.rm__zoom h3 { font-family:Georgia,serif; font-size:21px; color:var(--ink); margin:0 0 6px; }
.rm__zoom p { font-size:14px; line-height:1.6; color:var(--ink-soft); margin:0 0 10px; }
.rm__zstage.wiring { cursor:crosshair; box-shadow:inset 0 0 0 3px var(--bronze); }
/* ⛔ a second, identical .rm__zstage block lived here and shadowed
   the one above. Removed 6 Oct — two rules for one surface means
   every later change has a 50%% chance of editing the dead one. */
.rm__zstage .rm__p img { filter:drop-shadow(0 6px 10px rgba(0,0,0,.5)); }
@media (max-width:980px){ .rm__zooms { grid-template-columns:1fr; } }
.rm__note { display:none !important; }
  .rm { grid-template-columns:1fr; }
}

/* ---------- the cable palette (Packet Tracer picks the cable first) ------- */
.rw__cables {
  display:flex; gap:6px; align-items:center; flex-wrap:wrap;
  padding:7px 14px; background:var(--bg-soft); border-bottom:1px solid var(--rule);
}
.rw__cables b {
  font-family:'Courier New',monospace; font-size:8.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--bronze-deep); margin-right:4px;
}
.rw__cable {
  font-family:'Courier New',monospace; font-size:9.5px; letter-spacing:.1em;
  text-transform:uppercase; cursor:pointer; padding:6px 11px; border-radius:4px;
  background:var(--bg-card); color:var(--ink-soft); border:1px solid var(--rule);
}
.rw__cable:hover { border-color:var(--bronze); color:var(--ink); }
.rw__cable.on { background:var(--bronze); color:var(--bg-card); border-color:var(--bronze); }

/* ---------- the port picker ---------------------------------------------- */
.rw__ports {
  position:fixed; z-index:9999; max-height:300px; overflow-y:auto;
  background:var(--bg-card); border:1px solid var(--bronze); border-radius:6px;
  box-shadow:0 14px 36px rgba(26,35,50,.34); padding:6px; min-width:210px;
}
.rw__ports h5 {
  margin:4px 6px 6px; font-family:'Courier New',monospace; font-size:9px;
  letter-spacing:.2em; text-transform:uppercase; color:var(--bronze-deep);
}
.rw__port {
  display:grid; grid-template-columns:1fr auto; gap:10px; align-items:center;
  padding:7px 9px; border-radius:4px; cursor:pointer; font-size:12.5px;
  color:var(--ink);
}
.rw__port:hover { background:var(--bg-soft); }
.rw__port.dead { opacity:.34; cursor:not-allowed; }
.rw__port span { font-family:'Courier New',monospace; font-size:9px; color:var(--muted); }
.rw__port.used span { color:var(--bronze-deep); }

/* ---------- link lights on the piece -------------------------------------- */
.rw__lamp {
  position:absolute; width:9px; height:9px; border-radius:50%;
  border:1px solid rgba(0,0,0,.45); pointer-events:none; z-index:4;
}
.rw__lamp--green { background:#46C055; box-shadow:0 0 7px #46C055; }
.rw__lamp--amber { background:#E0A32E; box-shadow:0 0 7px #E0A32E; }
.rw__lamp--red   { background:#E0432E; box-shadow:0 0 9px #E0432E;
                   animation:rwblink .7s steps(2,end) infinite; }
.rw__lamp--off   { background:#4A4A4A; box-shadow:none; }
@keyframes rwblink { 50% { opacity:.25; } }

/* ---------- the signal marker --------------------------------------------- */
.rw__sig {
  position:absolute; width:15px; height:15px; border-radius:50%;
  background:var(--bronze-glow); border:2px solid #fff;
  box-shadow:0 0 14px var(--bronze-glow); pointer-events:none; z-index:8;
  transform:translate(-50%,-50%);
}
.rw__trace {
  margin-top:10px; border:1px solid var(--rule); border-radius:5px;
  background:var(--bg-card); overflow:hidden;
}
.rw__trace__h {
  padding:8px 13px; background:var(--bg-soft); border-bottom:1px solid var(--rule);
  font-family:'Courier New',monospace; font-size:9.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--bronze-deep);
}
.rw__hop {
  display:grid; grid-template-columns:26px 1fr 96px; gap:12px; align-items:baseline;
  padding:8px 13px; border-bottom:1px solid var(--rule); font-size:13px;
  color:var(--ink-soft);
}
.rw__hop:last-child { border-bottom:0; }
.rw__hop b { color:var(--ink); }
.rw__hop i {
  font-family:'Courier New',monospace; font-size:9px; color:var(--bronze-deep);
  font-style:normal;
}
.rw__hop span:last-child {
  font-family:'Courier New',monospace; font-size:11px; text-align:right;
  color:var(--bronze-deep); font-variant-numeric:tabular-nums;
}
.rw__hop.stop { background:#F6ECE8; color:#5A2A1C; }
.rw__hop.stop b { color:#5A2A1C; }
