/* ⛔ EXTENDED TO THE PITCH VIEW — 2026-08-19 ═══════════════════════════════════════════════
   The CEO hit this five separate ways tonight: "takes all content out of ipad and fullscreen",
   "brings this terrible top nav back", "crappy dock", "'open the brief' moves content out of
   ipad", "when I go to 'pitch it' it takes content out of ipad and is old style content".

   All five were ONE cause. This entire file — the thing that contains the game in the device
   and stands the legacy chrome down — was scoped to body[data-view="office"] and nothing else.
   The war room, the brief and the pitch flow are data-view="pitch", so they never adopted the
   shell: they kept the legacy topbar, the legacy dock and their own escaping layout. The
   migration was done for one room and left for the rest, which is why the game looked like two
   products depending on which screen you were on.

   Every selector below now covers EVERY in-game room, not a hand-listed pair — the CEO's own
   observation was that 'LOTS of links take us to ugly old content', and naming views one at a
   time is how this got half-done in the first place. The rule is now: a room is in-game unless
   it is boot/create/meetteam, and every in-game room wears the designed shell. Nothing else changed — no new
   layout, no restyling of the old chrome (that was the mistake this file was written to undo).
   ═══════════════════════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════════════════════
   SHELL ADOPTION — the game wears the designed chrome, and the legacy chrome stands down
   ══════════════════════════════════════════════════════════════════════════════════════════
   CEO, 18 Aug: "Build me the game site we designed yesterday. I NEVER want to see this shitty
   site again." · "update every screen to reflect the new design theme"

   The eight designed rooms build their rail, app bar and dock from `pn-shell.js` and take their
   palette from `pn-system-v4.css`. The game had its own hand-rolled topbar, icon rail and dock,
   and its own stylesheets. Two chromes cannot occupy one screen, so this file retires the game's
   and hands the surface to the designed one. Nothing here restyles the old chrome — that was the
   mistake of the whole preceding day. It removes it.
   ══════════════════════════════════════════════════════════════════════════════════════════ */

/* ── 1 · the legacy chrome stands down ─────────────────────────────────────────────────────
   Each of these is replaced by its designed counterpart, not merely hidden: the rail by
   `.rail`, the command bar by `.appbar`, the dock by `.dock`. Kept in the DOM rather than
   deleted because the game's own scripts still read and write them (badge counts, the end-week
   proxy, the account state) — removing the nodes would break behaviour that the shell does not
   yet own. Display is the only thing withdrawn. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .topbar,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .hub-nav,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .pnos-dock,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .masthead,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .dev-pin{display:none !important}

/* ── 2 · the game's canvas becomes the room's content well ────────────────────────────────
   `#app.wrap` carried the game's own page frame — its own max-width, padding and background.
   Inside `.content` that is the room's job, so the canvas goes transparent and full-bleed and
   lets the designed shell set the measure. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content > #app.wrap{
  max-width:none !important; width:100% !important;
  margin:0 !important; padding:0 !important;
  background:none !important; background-color:transparent !important;
  border:0 !important; box-shadow:none !important;
}
/* the hub grid was a two-column layout whose first column was the icon rail. The rail now lives
   outside `.content`, so the grid collapses to the single content column the rooms use. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .hud-main{
  display:block !important; grid-template-columns:none !important;
}

/* ── 3 · the ground. v4's rooms sit on the grouped ground with the field behind them; the game
   was painting its own near-black page. One ground, set once, so every screen matches the
   rooms rather than approximating them. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]){
  /* the DESK, not the screen. `--room` is the light studio surface the designed rooms sit the
     device on; `--grouped` is the ground INSIDE the glass and is set by `.screen`. Painting the
     body with `--grouped` is what made the game read as a flat dark page with a dead border
     round it instead of a device on a desk. */
  background:var(--room, #C2C7CD) !important;
}
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content{
  background:transparent !important;
}

/* ── 4 · the device case. The rooms draw their own `.pad/.dev/.screen` frame; the game draws a
   fixed bezel overlay. Two frames is one too many, and the shell's is the designed one. */
html.pn-cased body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .pn-case,
html.pn-cased body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .pn-bezel{display:none !important}

/* ── 5 · one title, not two. The shell writes the room's title row into `.content`; the game
   also renders its own masthead per view. Two identical headlines stacked is the exact fault
   the CEO reported twice on the rooms ("you STILL have two competing headlines — lose the
   second"). The shell's is the designed one, so the game's stands down inside the hub. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content .fl-mast,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content .fl-mast--room{display:none !important}

/* ── 6 · the NEXT strip stands down too ────────────────────────────────────────────────────
   `#pn-nextmove` was the game's own top band — "NEXT · END THE WEEK · nothing moves until you
   do". It sat above the content and now lands on top of the shell's app bar and title row.
   The instruction it carried is not lost: the same sentence and the same button already render
   inside the hub as the "Nothing moves until you do / End week N" module, which is where the
   comp puts the week's one action. One band, one place. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) #pn-nextmove{display:none !important}

/* ── 7 · the shell owns the top of the screen ─────────────────────────────────────────────
   The rooms scroll `.content` under a sticky app bar. The game's canvas was positioned against
   the viewport instead, which is what pushed the title under the strip above. Handing the
   scroll back to `.content` puts the app bar, the title and the content in the rooms' order. */
/* DEVICE FRAMING (Dave, 18 Aug). Two rules put the glass 132px out of square at the bottom:
   (a) `.screen{min-height:100vh}` here made the glass taller than its own case — the case is
   shorter than the viewport, so a 100vh floor overflows it. It fills the CASE, not the window,
   so this is 100%. (b) LAW 8 (pn-laws-20260816.css) sets `body{padding-bottom:132px}` as scroll
   clearance for the legacy dock — but the dock is hidden on the office (§1) and the shell's own
   dock is hidden above 1100px, so on the desk that 132px is dead space that shoves the device up.
   It is dropped on the office only; the law still governs every other surface. Insets are equal
   on four sides once both are gone (re-measured with tools/shots.js). */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .screen{min-height:100% !important}
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]){padding-bottom:0 !important; scroll-padding-bottom:0 !important}
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content{padding-top:0 !important}
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content > #app.wrap > *:first-child{margin-top:0 !important}

/* ── 8+10 · ONE DEVICE FRAME, AND IT IS THE DESIGNED ONE ──────────────────────────────────
   CEO: "now you have an ipad in an ipad", then "this horrible thick border".

   Both were the same fault, and I fixed them the wrong way round twice. There were genuinely two
   devices on the page: the SHELL's (pn-system-v4 — `.pad` is the desk, `.dev` is the case,
   `.screen` is the glass) and the GAME's legacy one (pn-ipad-shell.css, which sized <body> itself
   to 1280x884 and painted a graphite bezel as a box-shadow ring). My first go stripped the
   shell's frame and kept the game's; my second then tried to flatten the game's too, which left
   the whole app as a flat dark page inset 80px from the window with dead ground round it —
   the "thick border" in its final form.

   The correct call is not an override at all: the game's sheet is no longer loaded (see the note
   in play.html). Nothing in this file needs to touch `.pad`, `.dev` or `.screen` any more — the
   designed device draws itself, exactly as it does on floor.html, and this file's job goes back
   to being what its title says: retiring the legacy chrome.

   ⛔ The lesson, for the third time today: when two systems collide, remove one. Do not write a
   rule that makes the loser behave.

   ⛔ AND THE ONE FROM THE OLD SECTION 9, WHICH MUST NOT BE LOST TO A MERGE: a rule in this file
   once "mysteriously" failed to apply. It was not the cascade. The comment above it closed five
   lines early, so prose was being parsed as CSS, and a browser drops the declaration block that
   follows a parse error. That was the fourth bug in one day caused by a literal comment token —
   the fourth being the sentence that explained the third, which quoted the token and therefore
   closed the comment it was written inside. Never write the closing token inside a comment, in
   any quoting, for any reason. Name it in words. A comment is code. */

/* ── 11 · THE RED STRIP ───────────────────────────────────────────────────────────────────
   The pressure meter was drawn as a bare vertical bar pinned to the right edge of the game's
   old canvas. Inside the shell there is no canvas edge for it to belong to, so it reads as a raw
   red strip floating over the content with a stray "100" above it — the CEO's "weird red strip".
   It is real gameplay data (CEO-43) so it is not deleted; it stands down on this surface until
   it is rebuilt as a member of the designed system rather than an artefact of the old frame. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .tmeter,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .tmeter-v,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .tmeter-k,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .pressure-rail{display:none !important}

/* ── 12 · THE SPACING, WHICH IS THE WHOLE POINT ───────────────────────────────────────────
   CEO: "all the elegant design and spacing is gone." Correct — §2 stripped `#app.wrap`'s padding
   so the shell could set the measure, and then nothing set it, so every module ran edge to edge.
   The rooms hold their content off the rail and off the right edge and give the dock room to
   float; that inset is what makes them read as designed rather than dumped. It is declared here
   in the rooms' own terms so the game inherits the same rhythm rather than a copy of it. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content{
  padding:0 clamp(22px,3vw,44px) 104px !important;
  overflow-y:auto !important; overflow-x:hidden !important;
}
/* one scroller. The game's canvas was also scrolling, so the page had two — which is what makes
   a wheel gesture feel like it is fighting you. `.content` is the room's scroller; the canvas
   inside it simply grows. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content > #app.wrap{overflow:visible !important; height:auto !important}
/* the DESK does not scroll — the glass does. `.pad/.dev/.screen` are all height:100%, so the
   device is exactly one viewport tall and the only scroller on the page is `.content` inside it.
   Scoped to the office because the pre-game screens leave the wrappers entirely (see 13). */
/* ⛔ THE OVERFLOW LOCK EXCLUDES THE PITCH VIEW — 2026-08-19, and this was MY regression.
   Locking html/body to overflow:hidden is correct for a room whose content lives inside the
   shell's scrollable .content well: the well scrolls, the page does not. The pitch/war-room
   view does NOT put its content there — measured: .content was 0px tall on that view while the
   office's was 838. So the lock removed the page scroll without providing a working one, and
   the CEO could not scroll down to work on a brief at all. A cosmetic change that costs you the
   ability to play is not a trade, it is a break.
   The pitch view keeps every CHROME fix (legacy topbar and dock still stand down) and simply
   keeps its own page scroll until its layout is moved into the well properly.

   ⛔ THE LIST GREW, AND THAT IS THE REAL SIGNAL. pitch · store (the Vault) · weeksummary all
   render their content OUTSIDE the shell's .content well, so the lock takes their page scroll
   away without giving them a working one. Each was reported by the CEO as 'X doesn't scroll'
   and each was the same bug. Adding views to this exclusion list one at a time is a symptom
   fix: the actual work is to move those layouts INTO the well, and until that is done any new
   full-page view will arrive broken in exactly this way. Flagged in
   design/SPEC_2026-08-19_CEO_SCREEN_REDESIGNS.md as the biggest structural debt. That move is the
   real fix and it is not a job for the night before a demo. */
html:has(body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]):not([data-view="store"]):not([data-view="weeksummary"])){height:100% !important; overflow:hidden !important}
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]):not([data-view="store"]):not([data-view="weeksummary"])
{overflow:hidden !important; height:100% !important}
/* ⛔ AND THE ROOT ELEMENT WITH IT. The game carries an old document-scroll rule that forces
   `html{height:auto !important; overflow:visible !important}` — written years before the device
   existed, to stop the office clipping. pn-ipad-shell.css used to counter it; retiring that sheet
   let it back through, and the device immediately grew to 3,684px tall because `.pad/.dev/.screen`
   are all `height:100%` and 100% of `auto` is the content. Measured, not guessed: `.side` reported
   3684px against a 900px window. The device is exactly one viewport, and `.content` is the only
   thing that scrolls. */

/* ── 13 · P0 — THE PRE-GAME SCREENS ARE NOT INSIDE THE SHELL AT ALL ───────────────────────
   Two goes at this. The first hid the chrome but left `.screen` laying out a grid track for the
   rail that was no longer there, so MY AGENCIES rendered into a ~250px sliver. The second gave
   the wrappers `display:block; height:auto` — which fixed the width and broke the HEIGHT: the
   account stage sizes itself with `height:100%`, and a percentage height resolves against an
   ancestor chain that must have a definite height. `auto` broke that chain, so the stage
   collapsed to a band a couple of hundred pixels tall over the office backdrop. Second symptom,
   same mistake: I kept trying to make the shell's boxes BEHAVE on a screen that should not be
   inside them.

   So on any view that is not the office the wrappers stop being boxes at all. `display:contents`
   removes them from layout entirely and hands `#app` straight back to the body — which is
   exactly where it lived before the migration, and therefore exactly the layout the account
   module was written against. Nothing to size, nothing to collapse, no chain to break.

   ⛔ The wrappers are only ever a GAME-SCREEN device. If a future screen needs the shell, it
   should carry `data-view="office"` and get it deliberately, not inherit it by accident. */
/* ⛔ THE PITCH KEEPS ITS BOXES — 2026-08-20, P0.
   CEO: "Pitch and Brief Prep pages now DON'T SCROLL so I can't complete them."

   This is the missing half of moving the pitch into the device, and it is my error. I removed
   the pitch from the overflow lock's exclusion list — which takes the PAGE scroll away — while
   this rule was still dissolving .pad/.dev/.screen/.content to `display:contents` on every view
   that is not "office". `display:contents` removes an element from layout entirely, so .content
   was not a box, so the `overflow-y:auto` that makes every other room scroll had nothing to act
   on. Page scroll gone, well scroll never created: the screen simply stopped scrolling.

   The debt note two hundred lines above predicted this exact failure in these exact words —
   "the lock takes their page scroll away without giving them a working one". I read that note,
   removed the lock exclusion, and did not carry the other half.

   The pitch now keeps real boxes, like the office, so .content is a genuine scroller and the
   war room scrolls in the well like every other room. */
/* ⛔ THE VERDICT AND THE RESULT KEEP THEIR BOXES TOO — CEO, 2026-09-20, looking at a WON screen:
   "All this is still full screen and not in ipad."
   He is right, and the list above was the reason: every view except office and pitch had its
   .pad/.dev/.screen/.content dissolved to `display:contents`, which removes them from layout
   entirely - so on the verdict there is no case, no glass and no well, and the game spills across
   the whole browser window.

   ⛔ THE TWO LISTS MUST BE COMPLEMENTS, and that is the actual rule here rather than "add the
   screen he complained about". Line 185 locks html to overflow:hidden for every view EXCEPT
   boot / create / meetteam / store / weeksummary - those five own their whole viewport and scroll
   the page. Every OTHER view is page-locked, which means its scroll has to come from .content
   being a real box. A view that is page-locked AND box-dissolved has no scroll at all, which is
   exactly the P0 documented above ("Pitch and Brief Prep pages now DON'T SCROLL so I can't
   complete them") - the pitch was in precisely that state in August.
   verdict and result are page-locked, so they belong on this side of the line with office and
   pitch. The five viewport-owning views stay dissolved deliberately: giving them boxes would take
   their page scroll away without handing them a working one, which is the same bug from the other
   direction. */
/* ⛔ THE LIST WAS THE DEFECT, AGAIN. I added "verdict" and "result" to an allow-list of views
   that keep the device, and the CEO immediately found the next one: "then all other pitch pages
   go fullscreen - you are failing miserably." He is right, and this file already warned me in
   its own words a few hundred lines up - "THE LIST IS THE DEFECT. Enumerating surfaces one at a
   time guarantees a sixth appearance the next time somebody builds a full-bleed screen."

   So the rule is INVERTED to the thing I claimed it already was: the two lists are complements.
   The overflow lock at line 185 page-locks every view EXCEPT boot / create / meetteam / store /
   weeksummary - those five own their whole viewport and scroll the page. Those five, and only
   those five, dissolve their boxes. Every other view - known or not yet built - keeps a real
   case, glass and well, and therefore keeps a working scroller. A screen added tomorrow is
   cased by default instead of full-bleed by default, which is the right way round. */
html body:has(#app.wrap):is([data-view="boot"],[data-view="create"],[data-view="meetteam"],[data-view="store"],[data-view="weeksummary"]) .pad,
html body:has(#app.wrap):is([data-view="boot"],[data-view="create"],[data-view="meetteam"],[data-view="store"],[data-view="weeksummary"]) .dev,
html body:has(#app.wrap):is([data-view="boot"],[data-view="create"],[data-view="meetteam"],[data-view="store"],[data-view="weeksummary"]) .screen,
html body:has(#app.wrap):is([data-view="boot"],[data-view="create"],[data-view="meetteam"],[data-view="store"],[data-view="weeksummary"]) .content{
  display:contents !important;
}

/* ⛔ AND THE SIGN-IN SCREEN OWNS ITS OWN DEVICE — REGRESSION I SHIPPED, 2026-09-20.
   Inverting the rule above to "cased by default" was right for the game and wrong here: the
   signed-out /play screen draws its OWN device (account.js's .pn-stage → .pn-tablet, with the
   status bar and the home indicator), and account.js's own header says so in as many words -
   "account screens must NOT wrap themselves in their OWN full-viewport device... the ones drawn
   by html.pn-cased are the ONE device". With the shell's case suddenly kept on that screen there
   were TWO, so the login card rendered as a phone-width column jammed against a large empty
   panel. The CEO saw it before I did, on a preview I told him to test: "impressive. Not."

   Keyed off the auth card being present rather than off a view name, because the view name is
   exactly the thing that keeps being wrong. If the sign-in card is on screen, the shell's device
   stands down - there can only be one. */
html body:has(.pn-authwin) .pad,
html body:has(.pn-authwin) .dev,
html body:has(.pn-authwin) .screen,
html body:has(.pn-authwin) .content,
/* ⛔⛔ AND #pnStage IS NOT ONLY THE SIGN-IN CARD (CEO, 2026-09-20: "all these pages are still
   out of ipad- fail", after four separate rounds of me "fixing" the framing).

   THIS RULE WAS THE DEFECT. account.js reuses the id `pnStage` for the MY AGENCIES dashboard
   (account.js:1619, `u3-hold`) as well as the sign-in stage (:1344). So once a player signs in,
   any surviving #pnStage — even display:none, even torn down late — dissolved the device on
   EVERY screen of the game. That is why the pitch, the deck, the boardroom and the verdict all
   went full-bleed for him while every test I ran said they were cased: my tests boot from
   localStorage and never create a #pnStage at all, so they could not reproduce the one state
   that matters, the state of a player who actually signed in.

   MEASURED, on the booted game at 1600x1000: .screen is `grid` at x=131 w=1338 with no stray
   node, and `contents` at 0x0 the instant an empty hidden <div id="pnStage"> exists.

   The fix is not another name in a list — the list is what keeps being wrong. It is a condition
   that cannot be true during play: `html:not(.pn-cased)`. script-01.js toggles .pn-cased on
   exactly when there is a game (`!!S`), so this exception can now only fire on the pre-game
   screens it was written for, whatever id they happen to share. The .pn-authwin rule above stays
   unconditional as the belt to this braces: if the class were ever stale-on at sign-in, the auth
   card still stands the device down. */
html:not(.pn-cased) body:has(#pnStage) .pad,
html:not(.pn-cased) body:has(#pnStage) .dev,
html:not(.pn-cased) body:has(#pnStage) .screen,
html:not(.pn-cased) body:has(#pnStage) .content{
  display:contents !important;
}
html body:has(#app.wrap):not([data-view="office"]) .side,
html body:has(#app.wrap):not([data-view="office"]) .dock,
/* The designed app bar used to be hidden on every view except office, which is why a room
   that stood the legacy chrome down ended up with NO chrome at all. It now shows in every
   in-game room and hides only on the pre-game screens, which own their whole viewport. */
html body:has(#app.wrap)[data-view="boot"] .appbar,
html body:has(#app.wrap)[data-view="create"] .appbar,
html body:has(#app.wrap)[data-view="meetteam"] .appbar{display:none !important}

/* ── 14 · THE DESK IS NOT A CANVAS ────────────────────────────────────────────────────────
   With the designed device restored, `body` finally paints `--room` — the light studio desk the
   eight rooms sit on. It measured correctly (rgb(194,199,205)) and was still invisible, because
   the game paints five `position:fixed`, full-viewport atmosphere layers straight over it:

       canvas#mvc-fx · .mvc-veil · .mvc-grain · .bleed-text ×2   (the giant DISRUPT / MANIC words)

   They were authored when the game WAS the whole window, so filling the viewport was correct.
   Inside a device they are no longer backdrop — they are five sheets of dark laid over the desk,
   and they are why the first screenshot after the fix still read as a black page with a picture
   floating in it rather than a tablet on a surface. The atmosphere the rooms use lives on
   `.screen` (`--grouped` plus the field tokens) and is already there.

   ⛔ They are hidden, not deleted, and only on the office. The pitch and campaign sequences still
   run full-bleed and still want them; those move inside the shell this afternoon, and this rule
   is scoped so it cannot reach them. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) #mvc-fx,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .mvc-veil,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .mvc-grain,
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .bleed-text{display:none !important}

/* the legacy folio bezel — a fixed full-viewport overlay at z-index 9998 drawing the OLD case.
   It is the last survivor of the two-devices problem: invisible in a dark page, a grey wash over
   the desk the moment the desk became light. The device is drawn by `.dev` now. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) #pn-folio-frame{display:none !important}

/* THE RED STRIP, correctly addressed this time. §11 hid `.tmeter`/`.pressure-rail` — real classes,
   but not the ones on the page. The element the CEO photographed is `#pn-pressure`: a 26x322 bar
   fixed to the viewport's right edge with a bare "0" above it. Outside the device it has no edge
   to belong to, so it floats on the desk. Named by id, from a DOM dump, rather than guessed at
   from a stylesheet — which is how the first attempt missed. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) #pn-pressure{display:none !important}

/* ── 15 · THE FLOATING CHROME BELONGS ON THE GLASS, NOT ON THE DESK ───────────────────────
   Two controls are `position:fixed` to the WINDOW — the REPORT chip and the privacy banner —
   because they were written when the window was the app. Now they sit out on the desk, cutting
   across the device's rounded corner, which is the one detail that stops it reading as an object.

   They are re-anchored to the glass rather than re-parented, and the offsets are derived from the
   device's own geometry rather than eyeballed, so they hold at every width:

       .pad  padding 20px  ·  .dev  width min(100% , 1360px), centred, padding 11px

   so the glass starts `max(20px, (100vw - 1360px) / 2) + 11px` from the window edge. Add the
   rooms' own 16px gutter and the chip lands inside the screen at 1280, 1440, 1680 and 1920 alike.
   ⛔ If `.dev`'s max width or padding ever changes, this expression changes with it — it is
   written as the same arithmetic, not as a number that happens to match today. */
html body:is([data-view="office"],[data-view="store"],[data-view="pass"]) #pnfb-chip{
  left:calc(max(20px, (100vw - 1360px) / 2) + 27px) !important;
  bottom:47px !important;
}
/* PR1c item 1 (CRITICAL, mobile): below 640 the hero CTA row ("Win your first pitch →") runs
   near-full-width along the bottom of the glass, and the bottom-left anchor above lands the chip
   directly on top of it — hiding "Win your." at 390. There is no free bottom-edge real estate at
   this width (the CTA owns it), so the chip moves OFF that axis entirely: a slim vertical tab
   docked to the mid-right edge, clear of the top app bar and clear of every bottom CTA at any
   scroll position. `.content` also gets a touch more bottom clearance so the last card in the
   scroller — CTA included — never sits flush against the viewport edge.

   ⛔ GLOBAL, NOT OFFICE-ONLY (2026-08-18, coordinator ruling during the neon sweep): the REPORT
   chip is SHARED shell — it floats over EVERY game view, so a fix scoped to `data-view="office"`
   left the same overlap on the Vault (`store`) and the Season Pass sheet (`pass`), and would ship
   it on every view the sweep hasn't reached. The hub's own sub-views (pitches / clients / team /
   financials / season = `.hub-view[data-view="v-*"]` INSIDE `body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"])`) were
   already covered; this widens it to the two OTHER shell data-views so the chip is clear of content
   on mobile everywhere at once. One shared fix, every view. (The later burger work makes this same
   edge-tab the proper mobile-nav entry; the overlap itself is now closed globally.) */
@media (max-width:640px){
  html body:is([data-view="office"],[data-view="store"],[data-view="pass"]) #pnfb-chip{
    left:auto !important; right:4px !important;
    top:50% !important; bottom:auto !important;
    transform:translateY(-50%) !important;
    min-width:0 !important; min-height:0 !important;
    padding:10px 6px !important;
    writing-mode:vertical-rl !important; text-orientation:mixed !important;
    border-radius:10px !important;
  }
  html body:is([data-view="office"],[data-view="store"],[data-view="pass"]) .content{
    padding-bottom:calc(104px + 32px) !important;
  }
}
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) #pn-consent{
  left:calc(max(20px, (100vw - 1360px) / 2) + 11px) !important;
  right:calc(max(20px, (100vw - 1360px) / 2) + 11px) !important;
  width:auto !important;
  bottom:31px !important;
  border-radius:0 0 24px 24px !important;   /* it meets the glass's own bottom corners */
}

/* ── NEON CHROME — the shared shell reads the theme accent (office neon PR, 2026-08-18) ─────
   The app-bar icons (Store bag, Guide "?", mail), the rail's active-view icon glow and the
   room icons all colour their accent from v4's --acc / --v4-acc. pn-design-0817.css §0 re-pins
   BOTH to brand-orange #F97316 on the bare `[data-palette]` selector, which beats mvc-os.css's
   neon-onyx palette by load order — so on the neon theme the chrome stayed orange while the
   content went pink/teal. That is the milder repeat of the #564 clash the CEO would flag.

   Re-pin the accent to the neon spine for the neon palette, SCOPED TO THE CHROME CONTAINERS
   ONLY (.appbar / .side / .dock). Two consequences, both intended:
     · it fixes the chrome on EVERY game view at once (the shell is shared) — high value;
     · it does NOT reach any view's CONTENT, so an unswept room keeps its orange content until
       its own PR rather than gaining a half-pink clash now.
   `body[data-palette="neon-onyx"] .appbar` (attr + type + class) outranks the `[data-palette]`
   repin, so no !important is needed.

   ⛔ KEEP FIXED, and these do NOT read --acc so this rule cannot touch them: the PITCHNOIR / NOIR
   wordmark (.mark img, .side .wm — retrieved brand asset, brand-mark guard) and the .rfi-mono
   monogram; and the SEMANTIC colours — --play (Arcade/Duff gold), green "surging", amber "WATCH",
   the orange severity/"NAIL-BITER" dots — which carry MEANING, not brand accent. */
/* DARK IS ORANGE (Rita, 2026-08-19). neon-onyx is the base palette for Dark. (Neon theme retired
   2026-09-12 — CEO: "remove neon and just have light and dark"; there is no second dark UI theme
   for the rail/appbar/dock to differ against any more.) */
html body[data-theme="dark"][data-palette="neon-onyx"] .appbar,
html body[data-theme="dark"][data-palette="neon-onyx"] .side,
html body[data-theme="dark"][data-palette="neon-onyx"] .dock{
  --acc:#F97316; --v4-acc:#F97316; --v4-acc-ink:#07080C; --glow:249,115,22;
}

/* ── ACCENT DISCIPLINE (PR1c, items 4+5) — one loud fill per view, one identity role per icon ──
   The hero "Win your first pitch" glass is the view's ONE solid accent fill. Everything else in
   the shared chrome that was carrying pink — the Store pill's fill and the agency crest icon —
   is decoration wearing the same colour as the CTA and the active-nav indicator, which is the
   exact "accent sprinkled everywhere" tell. Un-themed (no [data-palette] scope) so the demotion
   holds under dark/neon/light alike, matching how the rest of the appbar chrome is written. */

/* item 4 — the Store pill goes back to a neutral chip; only the coin COUNT keeps a touch of
   accent, so it reads as a number worth noticing, not a second CTA competing with the real one. */
.appbar .store{background:var(--card-2) !important;color:var(--label) !important}
.appbar .store svg{stroke:var(--label3) !important}
.appbar .store b{color:var(--acc) !important}

/* item 5 — pink's only identity role in the chrome is the rail's active-view indicator (kept,
   untouched, in the NEON CHROME block above). The agency crest is a portrait frame, not a nav
   state, so its icon reads neutral ink like every other non-active glyph in the rail/appbar. */
.appbar .agency .crest svg{stroke:var(--label2) !important}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   THEME-FOLLOWING DEVICE SURROUND — the device sits on a real SURFACE (CEO 2026-08-19, signed
   off ×2). DARK → warm WOODEN TABLETOP; LIGHT → cool WHITE MARBLE. This RETARGETS the flat
   `--room` desk (item 3 above): the live surround is the BODY behind `.pad` (proved on the running
   hub: body.pn-folio paints the desk, `.pad` padding is the visible margin, `.dev` is the device
   case). We are NOT reviving the retired graphite bezel — the clean `.dev` case + its cast stay;
   we only (a) grow `.pad` so a real surface shows around the device, and (b) texture the body.
   CSS-only textures (inline SVG grain/veining) — nothing through the media/ai_label gates.
   Desktop shell only; the <=720px full-bleed `.pad{padding:0}` (pn-system-v4) is untouched. ── */
@media (min-width:1025px) and (pointer:fine){
  /* (a) more desk shows, so wood/marble reads as a SURFACE the device sits on, not a border. */
  html.pn-cased body.pn-folio .pad{ padding:clamp(30px,3.4vw,66px) !important; }

  /* (a2) CONTACT SHADOW — a tight, dark occlusion right at the device base so it reads as RESTING
     on the surface, not floating. Keeps pn-system-v4's soft cast + inset hairline, adds the near
     shadow. Both themes; tuned per theme so it grounds on wood AND on the paler marble. */
  html.pn-cased body.pn-folio .dev{
    box-shadow:
      0 1px 2px rgba(0,0,0,.72),         /* the seam — near-black, hugging the base edge */
      0 3px 7px rgba(0,0,0,.55),         /* tight contact */
      0 8px 20px rgba(0,0,0,.34),        /* near ambient */
      0 28px 64px rgba(20,14,6,.52),     /* the soft cast into the room */
      inset 0 0 0 1px rgba(255,255,255,.07) !important;
  }
  html.pn-cased[data-theme="light"] body.pn-folio .dev,
  html.pn-cased body.mvc-light.pn-folio .dev{
    box-shadow:
      0 1px 2px rgba(34,28,20,.6),       /* the seam on stone — crisp, so it sits not floats */
      0 3px 8px rgba(40,34,26,.4),
      0 9px 22px rgba(40,34,26,.26),
      0 28px 62px rgba(60,50,36,.26),
      inset 0 0 0 1px rgba(255,255,255,.5) !important;
  }

  /* (b) WOOD — default + every dark pack (neon carries no data-theme, so it lands here too).
     1 grain (SVG feTurbulence, brown low-alpha) · 2+3 TWO plank-seam gradients on different periods
     (146px & 211px) so seams don't read as one stamped ruler · 4 tonal bands · 5 vignette+key ·
     6 deep-walnut base (SST warm brown-grey family #584237/#4a3b33, not flat brown). */
  html.pn-cased body.pn-folio{
    background:
      url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='760'%20height='460'%3E%3Cfilter%20id='g'%20x='0'%20y='0'%20width='100%25'%20height='100%25'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.0035%200.09'%20numOctaves='3'%20seed='7'%20stitchTiles='stitch'%20result='n'/%3E%3CfeColorMatrix%20in='n'%20type='matrix'%20values='0%200%200%200%200.14%20%200%200%200%200%200.08%20%200%200%200%200%200.035%20%200%200%200%201.25%20-0.52'/%3E%3C/filter%3E%3Crect%20width='100%25'%20height='100%25'%20filter='url(%23g)'/%3E%3C/svg%3E"),
      repeating-linear-gradient(180deg,
        rgba(0,0,0,0) 0, rgba(0,0,0,0) 146px,
        rgba(0,0,0,.20) 147px, rgba(0,0,0,.20) 148px,
        rgba(255,255,255,.028) 149px, rgba(0,0,0,0) 151px),
      repeating-linear-gradient(180deg,
        rgba(0,0,0,0) 0, rgba(0,0,0,0) 209px,
        rgba(0,0,0,.12) 210px, rgba(255,255,255,.022) 212px, rgba(0,0,0,0) 214px),
      linear-gradient(94deg,
        rgba(84,54,34,.0) 0%, rgba(120,80,48,.16) 22%, rgba(58,36,22,.16) 48%,
        rgba(116,78,46,.14) 74%, rgba(52,32,20,.10) 100%),
      radial-gradient(150% 120% at 50% 4%,
        rgba(120,82,50,.55) 0%, rgba(78,50,30,.30) 34%, rgba(0,0,0,0) 58%),
      radial-gradient(135% 128% at 50% 46%,
        #6a4529 0%, #563922 30%, #402716 62%, #2c1a0f 84%, #1c110a 100%) !important;
    background-size:760px 460px, auto, auto, auto, auto, auto !important;
    background-blend-mode:overlay, normal, normal, soft-light, screen, normal !important;
  }

  /* (c) MARBLE — LIGHT pack (mvc-os sets html[data-theme="light"]; body.mvc-light as belt-and-braces).
     WARM Carrara, not cool slate. 1 stronger warm-grey grain (OVERLAY, so it bites a light base) ·
     2-5 FOUR veins of differing width/opacity, one broken across two close angles (118/121deg) so it
     drifts instead of ruling a straight line · 6 warm top raking light · 7 warm-white base. */
  html.pn-cased[data-theme="light"] body.pn-folio,
  html.pn-cased body.mvc-light.pn-folio{
    background:
      url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='700'%20height='560'%3E%3Cfilter%20id='m'%20x='0'%20y='0'%20width='100%25'%20height='100%25'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.010%200.012'%20numOctaves='6'%20seed='11'%20stitchTiles='stitch'%20result='n'/%3E%3CfeColorMatrix%20in='n'%20type='matrix'%20values='0%200%200%200%200.34%20%200%200%200%200%200.32%20%200%200%200%200%200.28%20%200%200%200%200.8%20-0.36'/%3E%3C/filter%3E%3Crect%20width='100%25'%20height='100%25'%20filter='url(%23m)'/%3E%3C/svg%3E"),
      linear-gradient(112deg,
        rgba(122,114,98,0) 8%, rgba(122,114,98,.22) 12%, rgba(122,114,98,0) 16%),
      linear-gradient(115deg,
        rgba(112,104,88,0) 9%, rgba(112,104,88,.13) 12.5%, rgba(112,104,88,0) 15%),
      linear-gradient(60deg,
        rgba(110,104,90,0) 46%, rgba(110,104,90,.17) 50%, rgba(110,104,90,0) 55%),
      linear-gradient(38deg,
        rgba(134,124,104,0) 78%, rgba(134,124,104,.16) 83%, rgba(134,124,104,0) 88%),
      radial-gradient(150% 120% at 50% 2%,
        rgba(255,253,247,.85) 0%, rgba(255,253,247,0) 44%),
      radial-gradient(135% 130% at 50% 48%,
        #faf8f3 0%, #f0ede4 42%, #e3ddd0 72%, #d6d0c2 92%, #cbc4b3 100%) !important;
    background-size:700px 560px, auto, auto, auto, auto, auto, auto !important;
    background-blend-mode:overlay, normal, normal, normal, normal, screen, normal !important;
  }

  /* (d) NIGHT SKY, the Neon-theme desk surround, retired 2026-09-12 (CEO: "remove neon and just
     have light and dark") — data-theme can no longer be "neon" so this dead selector is deleted. */
}

/* ── 16 · IN-SHELL ROOMS — Arcade and The Duff open OVER the office, never out of it ───────
   The off-hours rooms are standalone, gated pages in the old design. pn-shell-adopt.js hosts
   them in a same-origin overlay iframe (the origin carries the clearance, so the countdown gate
   is never seen) and the framed room draws content-only (pn-shell.js suppresses its own chrome
   when window.self !== window.top). This is the overlay's own chrome: a slim header with the
   room name and a single "back to the office" control, over a full-bleed frame. Colours read the
   shell tokens already resolved on this surface (the app bar uses the same --acc / --label /
   --card-2), each with a solid fallback so the overlay is never unstyled. The z-index clears the
   shared floating chrome (REPORT chip 9998, folio 9998). */
/* ⛔ THE ROOM OPENS IN THE DEVICE, NOT OVER IT (CEO 2026-08-20) ═════════════════════════════
   "I want you to frame the Arcade & Duff content IN the ipad — only when they click to play the
    games themselves or Enter the Duff do we go full screen."

   It was position:fixed;inset:0, so browsing the Arcade threw the player out of the device and
   filled the browser window — the same escape that made the pitch flow feel like a different
   product. Browsing a room is still being IN the agency; only playing a game is leaving it.

   So: a window, inset to the device's measure, with the surface dimmed behind. The full-screen
   state is opt-in via .is-full, which the games themselves ask for (see pn-shell-adopt.js). */
.pn-room-ovl{
  position:fixed; inset:0; z-index:10050;
  display:grid; place-items:center;
  padding:clamp(14px,3.5vh,44px) clamp(14px,3.5vw,52px);
  background:rgba(6,8,13,.72); backdrop-filter:blur(3px);
  animation:pnRoomIn .18s ease both;
}
.pn-room-ovl__win{
  display:flex; flex-direction:column;
  width:min(1180px,100%); height:min(860px,100%);
  border-radius:18px; overflow:hidden;
  background:var(--grouped, #0b0c10);
  border:1px solid rgba(255,255,255,.14);
  box-shadow:0 48px 110px rgba(0,0,0,.66);
}
/* PLAYING is leaving the office — the game gets the whole screen, and keeps a real way back */
.pn-room-ovl.is-full{ padding:0; background:var(--grouped,#0b0c10); backdrop-filter:none; }
.pn-room-ovl.is-full .pn-room-ovl__win{
  width:100%; height:100%; border-radius:0; border:0; box-shadow:none;
}
/* on the desktop stage the room is placed on the device screen (pn-shell-adopt.js openRoom) and fills it, played or browsed */
.pn-room-ovl.pn-room-cased{ padding:0; overflow:hidden; background:var(--grouped,#0b0c10); backdrop-filter:none; }
.pn-room-ovl.pn-room-cased .pn-room-ovl__win{ width:100%; height:100%; border-radius:0; border:0; box-shadow:none; }
@keyframes pnRoomIn{ from{opacity:0} to{opacity:1} }
.pn-room-ovl__bar{
  position:relative; flex:0 0 auto;
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding:11px clamp(14px,3vw,30px) 11px 66px;
  background:var(--card-2, #14151b);
  border-bottom:1px solid rgba(128,128,128,.22);
}
/* the same traffic lights as the interview, the sign-in and the wire notice — one window
   language rather than a bespoke bar per room */
.pn-room-ovl__bar::before{
  content:''; position:absolute; left:clamp(14px,3vw,30px); top:50%; transform:translateY(-50%);
  width:38px; height:10px;
  background:
    radial-gradient(circle 5px at 5px 5px,#FF5F57 98%,transparent 100%) 0 0/14px 10px no-repeat,
    radial-gradient(circle 5px at 5px 5px,#FEBC2E 98%,transparent 100%) 14px 0/14px 10px no-repeat,
    radial-gradient(circle 5px at 5px 5px,#28C840 98%,transparent 100%) 28px 0/14px 10px no-repeat;
}
.pn-room-ovl__ttl{
  font:700 14px/1 var(--num, ui-monospace, "JetBrains Mono", monospace);
  letter-spacing:.14em; text-transform:uppercase;
  color:var(--label, #e9eaee);
}
.pn-room-ovl__x{
  display:inline-flex; align-items:center; gap:8px;
  cursor:pointer; border:0; border-radius:999px;
  padding:9px 16px;
  font:600 13px/1 var(--sans, system-ui, sans-serif);
  background:var(--acc, #FF2E88); color:var(--v4-acc-ink, #07080C);
}
.pn-room-ovl__x:hover{ filter:brightness(1.06) }
.pn-room-ovl__x:focus-visible{ outline:2px solid var(--label, #fff); outline-offset:2px }
.pn-room-ovl__frame{
  flex:1 1 auto; width:100%; min-height:0;
  border:0; display:block;
  background:var(--room, #0b0c10);
}
body.pn-room-open{ overflow:hidden !important }
@media (max-width:520px){
  .pn-room-ovl__x span{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0) }
  .pn-room-ovl__x{ padding:9px 12px }
}

/* ── 9 · THE ROOM HOLDS ITS CONTENT (CEO 2026-08-19) ─────────────────────────────────────────
   "it takes all content out of ipad and fullscreen" · "'open the brief' moves content out of
   ipad" · "'pitch it' takes content out of ipad".

   #app.wrap IS inside the shell's .content well — measured and confirmed. But the game's own
   views set their own widths and run edge-to-edge, so they overflow the well rather than sit in
   it: .content measured 0 wide while #app rendered at the full 1440. The device frame was
   therefore decoration, not a container, which is exactly how it read.

   This constrains the game's canvas to the shell's own measure and centres it, so every room —
   war room, brief, pitch, clients — is held by the frame instead of escaping it. Deliberately a
   CONSTRAINT rather than a re-architecture: the night before a demo, the safe fix is to bound
   the overflow, not to rebuild the layout that causes it. The proper fix is to give the deep
   views the shell's grid, which is Saturday's work. */
/* ⛔ THE PITCH NOW ADOPTS THE SHELL — 2026-08-20.
   CEO, repeatedly and finally: "why can you NOT put all this Pitch and Brief PREP content in
   iPad? So everything is in the iPad, NOT full screen."

   The exclusion above was not stubbornness, it was a real constraint: the war room was a
   TWO-column layout (work left, build-sheet rail right) and the shell's 1180 well crushed the
   rail — "Team on the job" wrapped onto four lines and the page read as squashed. The note said
   the real fix was to move the layout into the well, and that it was "not a job for the night
   before a demo".

   That constraint is gone. The pitch became ONE column earlier today, on the CEO's own
   instruction ("clean this all up into one column"), and a single column is exactly what the
   well was built for. So the exclusion is removed everywhere it appears — the measure cap and
   the overflow lock both — and the pitch, the brief and the war room now sit inside the device
   like every other room, scrolling in the well rather than taking the page scroll with them.

   The structural debt flagged in SPEC_2026-08-19 is paid, and it was the one-column decision
   that paid it. */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content > #app.wrap{
  max-width:min(1180px, 96vw) !important;
  margin-inline:auto !important;
}
/* anything inside that still declares its own full-bleed width is pulled back to the well */
html body[data-view]:not([data-view="boot"]):not([data-view="create"]):not([data-view="meetteam"]) .content > #app.wrap > *{
  max-width:100% !important;
}
/* the war room's own hero bled past the panel edge — it is a room, not a page */
/* the war-room hero clamp went with the measure cap — the view owns its own layout. */

/* ══ THE PITCH'S OWN FURNITURE SITS ON THE DESK, NOT IN THE DEVICE (CEO 2026-09-20) ═══════════
   "main complaint on all Pitch experience is everything STILL lives outside the ipad and it
   needs to live IN it - this was so clearly briefed so many time."

   He is right that it was briefed, and the reason it kept coming back is that each fix named the
   VIEWS it covered. The block above re-anchors the REPORT chip for office/store/pass - and the
   pitch was never in that list, so on the one screen he spends the most time in, the chip and the
   theme float stayed pinned to the browser, cutting across the device's corner.

   MEASURED on the booted game at 1600x1000, pitch view, before this rule:
       glass (.screen)   x=131  w=1338
       .mvc-palfloat     x=1508 (78 wide)   - 39px outside the glass's right edge
       #pnfb-tab         x=1579             - hard against the browser edge
   The stage rail was the third and worst offender; that one is fixed at source (it is now mounted
   INSIDE .content - see pnStageRail) because a rail is chrome, not a floating control.

   Offsets are the device's own arithmetic, not eyeballed numbers, exactly as the block above:
       .pad padding 20px · .dev width min(100%,1360px) centred, padding 11px
   ⛔ Same warning as above: if .dev's max width or padding changes, this expression changes with
   it. And the view list is now every view the case is on - do not narrow it again. */
html.pn-cased body .mvc-palfloat,
html.pn-cased body #pnfb-tab{
  right:calc(var(--pn-glass-r, max(20px, (100vw - 1360px) / 2) + 11px) + 16px) !important;
}
html.pn-cased body .mvc-palfloat{
  bottom:calc(var(--pn-glass-b, 47px) + 16px) !important;
}
