/* ══════════════════════════════════════════════════════════════════════════════════════════════
   THE LAW SHEET — loaded LAST in play.html, on purpose.

   WHY THIS FILE EXISTS
   Rita, 2026-08-16: "play.html legacy CSS (~1,370 !important) — the laws can't reach the game
   until that's hand-resolved."

   She is right about the symptom. The real count is 2,299 `!important` declarations across the 25
   stylesheets play.html loads (style-01.css alone holds 1,370 — I had previously quoted that one
   file's count as the whole cascade, which was wrong).

   Hand-resolving 2,299 declarations is weeks of work and it is not what unblocks design. What
   unblocks design is a place where a law can be written and RELIABLY WIN. That is this file. It
   is last in the cascade, so for equal specificity and equal importance it takes the tie — which
   is the whole mechanism, and the reason no `@layer` is used here.

   ⛔ DO NOT WRAP THIS FILE IN @layer. For `!important` declarations, layer order REVERSES: an
   earlier layer beats a later one. Layering this sheet would hand the win back to style-01.css's
   1,370 important rules. This was recommended once and it was wrong; the note stays so it is not
   recommended again.

   HOW TO USE IT
   - A rule here must be a LAW — something true on every surface, traceable to design/UX_RULES.md
     or a CEO ruling. Component styling belongs in the component's own sheet.
   - Match the specificity of the rule you are overriding, and no more. Specificity inflation is
     how the other 25 sheets got into this state.
   - Every rule carries the law it enforces and, where one exists, the rule it is beating.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── LAW 1 · THE 44px TAP FLOOR APPLIES AT EVERY WIDTH ────────────────────────────────────────
   UX_RULES: "tap floor 44px, everywhere, no exceptions."

   THE DEFECT THIS FIXES. The floor was already written — pn-touch-20260801.css:27 sets
   `.topbar .tb-btn{ min-height:44px !important }`. It has never applied anywhere except a phone,
   because the whole block sits inside `@media (max-width: 480px)`. Measured on the live game at
   1280px: `.topbar .tb-btn` computes to height 30px, min-height auto, across 9 buttons.

   Touch does not stop at 480px. iPads, hybrid laptops and any phone turned landscape all sat
   below the floor. The law was written as a mobile fix when it is a universal one, so it is
   restated here without a width gate.

   min-height rather than height: min-height clamps a smaller explicit height (style-01.css:9751
   sets `height:30px !important`), so the box grows to 44px without us having to out-specify a
   fixed height on every control. */
.topbar .tb-btn,
.hub-tab,
.poap-dossier,
.mt-toggle button,
.wr-back, .pn-back { min-height: 44px !important; }

/* Found by sweeping the rendered DOM rather than by reading the sheets — every one is a real
   <button> with a real label, and none was in the original mobile-only block:
     .nm-go   "End the week ▸"  was 28px — the PRIMARY action of the whole week loop
     .ts-chip  Wren68, Quinn52…  was 36px — the team-member selectors
   A 28px primary action is the clearest case there is for why this law is not a mobile concern. */
.nm-go,
.ts-chip { min-height: 44px !important; }
.rv-opt { min-height: 48px !important; }
#pn-consent .pnc-yes, #pn-consent .pnc-no { min-height: 48px !important; }

/* The icon-only topbar buttons are square: give them the floor on BOTH axes, or a 44px-tall
   30px-wide target still fails the law in the direction people actually miss. */
.topbar .tb-btn.tb-ico { min-width: 44px !important; }

/* KNOWN EXCEPTION, on the record rather than silently ignored: `.lg-dot` (12px) is left alone.
   It is a status indicator, not a control — enlarging it to satisfy a metric would break the
   composition it belongs to. It is separately flagged for replacement on IP grounds (the
   red/amber/green cluster is macOS trade dress and we are commercial), which is Jon's call. */

/* ── LAW 2 · NO ITALIC IN UI OR BODY TEXT ────────────────────────────────────────────────────
   CEO 2026-08-15: "only use Italics like this on the motion graphics in the films."
   CEO 2026-08-16 amended this for DISPLAY headlines only — those are now oblique by law. Body
   and UI text stayed banned, and the game still renders 5 italic display elements.

   Scoped to the offenders the audit actually named — `.bleed-text` and `.brandmark` — rather
   than a blanket `*{font-style:normal}`, which would also flatten the approved oblique headline
   and any real `<em>` doing its job in prose. */
.bleed-text, .brandmark, .brandmark-mark { font-style: normal !important; }

/* ── LAW 3 · THE ACCENT IS THE LOGO ORANGE ───────────────────────────────────────────────────
   CEO 2026-08-16: "make sure if you used orange as a highlight, to match the PN logo orange."
   #F97316, sampled from pitchnoir-orange.png and matching the 462 uses already across web/.
   Declared as tokens so a surface that reads the token gets it for free; surfaces still holding
   a literal hex are a separate sweep and are NOT force-overridden from here, because a blanket
   colour rule would repaint things this sheet cannot see. */
:root {
  --pn-accent:      #F97316;
  --pn-accent-ink:  #B04D08;   /* accent-coloured TEXT on paper — 4.52:1 AA */
  --pn-on-accent:   #180A02;   /* the label ON the orange — 6.92:1 AA */
}

/* ── LAW 4 · FOCUS IS ALWAYS VISIBLE ─────────────────────────────────────────────────────────
   UX_RULES. A keyboard user must be able to see where they are. Several legacy sheets set
   `outline:none` on hover/focus states; this restates the floor without touching the rest. */
:focus-visible { outline: 2.5px solid var(--pn-accent) !important; outline-offset: 2px !important; }

/* ── LAW 5 · MOTION SAFETY ───────────────────────────────────────────────────────────────────
   Respect the OS setting. Scoped to animation/transition only — `scroll-behavior` is left to the
   component sheets, since forcing it here has broken in-page anchoring before. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ── LAW 6 · THE 11px TYPE FLOOR ─────────────────────────────────────────────────────────────
   UX_RULES §1 (LEGIBILITY) + tools/mobile_audit.js, which has encoded 11px as the phone floor
   since 2026-08-10: "unreadable at arm's length on a phone."

   THE DEFECT THIS FIXES, measured on the live game at 390px across Perf / Floor / Hires / NBOs /
   Clients / Season / Sycophant: **33 distinct elements set between 7px and 10px.** The floor was
   written into the audit tool but never into the product, so every run reported it and nothing
   consumed the report. Worst offenders: the PN/OS phone tile labels at 7.5px, the season plate
   tags at 7.5px, `/OS` at 7px, the mono eyebrows at 9px, and `END WEEK` — the most-pressed
   action in the game — at 9.5px.

   WHY THIS IS WORSE THAN THE NUMBER LOOKS. Nearly every offender is uppercase JetBrains Mono at
   0.14–0.24em tracking. Tracked-out uppercase reads a full step smaller than its nominal size
   because the eye gets no word-shape to lock onto, so 9px tracked mono is doing the work of about
   7px set normally. This is the "tactical micro-copy" motif (SST §3.8) taken past the point where
   it communicates, which is the definition of decoration.

   THE RULE, AND WHY IT IS NOT ONE NUMBER. Roles get different floors, because a floor that treats
   a decorative stamp and a primary action as the same thing is how you get a uniform, characterless
   result — the SST's whole point is hierarchy. Decoration gets 11px; anything a player must READ
   to decide gets 11.5px; anything a player must PRESS gets 12px. Scale contrast is preserved:
   these all still sit far below the 16px body and the display sizes, so the mono voice stays a
   whisper — it just stops being an inaudible one.

   Scoped to the classes the audit named, never a blanket `*`, so nothing this sheet cannot see
   gets repainted. Sizes are the floor only — a surface already above it is untouched. */

/* 6a · DECORATION AND STAMPS — read once, never acted on. Floor 11px. */
.pnos-stamp-lb,
.sea-plate-live, .sea-plate-tag, .sea-rung-tag, .sea-rung-state,
.tm-floor-rec, .tm-floor-k,
.syco-foot, .syco-date,
.pnos-os-stamp { font-size: 11px !important; }

/* 6b · LABELS AND EYEBROWS THE PLAYER MUST READ TO DECIDE — the mono voice that names what a
   number IS. A KPI whose label cannot be read is a number with no meaning. Floor 11.5px. */
.tac-eyebrow, .perf-hero-eyebrow,
.mvc-kpi-lbl, .pv-hero-lbl, .pv-hd-k, .pv-pill,
.nbo-bb-k, .nbo-bb-eye, .nbo-bb-sub,
.s2-eyebrow, .s2-bk-k, .s2-scrub-wk,
.sea-rung-up { font-size: 11.5px !important; }

/* 6c · CONTROLS — a label on a thing you press. The 44px tap floor (LAW 1) gave these an
   honest target; this gives them an honest label. Floor 12px.
   `END WEEK` and the PN/OS tiles are the two most-used controls in the game and were the two
   smallest — 9.5px and 7.5px. That inversion of importance and weight is UX_RULES §15.3
   ("EARNS ITS WEIGHT") failing in the quiet direction. */
.topbar .tb-btn.tb-endweek,
.pnos-tile-lb,
.syco-back,
#pnfb-chip { font-size: 12px !important; }

/* 6d · SPECIFICITY-MATCHED RESTATEMENTS. The five rules below exist only because a legacy sheet
   states the same property at higher specificity, so the plain class selector above loses even
   with `!important`. Each is matched to its opponent and no higher — the discipline this file's
   header asks for. The opponent is named so the day it is deleted, this can be too. */

/* beats style-01.css:6616  body[data-view="office"] .tac-eyebrow{font-size:9px !important} */
body[data-view="office"] .tac-eyebrow,
body[data-view="office"] div.tac-eyebrow { font-size: 11.5px !important; letter-spacing: .12em !important; }

/* The dock stamps put their text in a bare inner <span>, so sizing the button does nothing.
   `/OS` and the week clock were the two smallest strings in the product at 7px. */
.pnos-os-stamp > span,
.pnos-dock-clock > span { font-size: 11px !important; }

/* ⚠ REGRESSION FIXED HERE — recorded rather than quietly patched, because the numeric audit did
   not catch it and only the render did.

   Raising the dock type above (tile labels to 12px, end caps to 11px) made the PN/OS dock collide
   at 390px: the `PN /OS PHONE` stamp overlapped the EMAIL label, and the week clock overlapped
   THE PUB — measured, the clock begins at x=285 while THE PUB's label runs to x=343. Four labelled
   tiles plus two text end caps do not fit in 390px at a legible size. They never did; at 7px the
   overlap was simply too small to see.

   The fix is to DELETE, not to shrink back below the floor — UX_RULES §15, "ask what this pass
   deletes", and the standard responsive answer: drop content at narrow widths rather than reduce
   it to an unreadable size. On phones the stamp keeps its `/OS` mark and loses the word `PHONE`
   (the dock is self-evidently the phone), and the clock keeps the week and loses the season
   fraction, which is stated on the Season surface anyway. Both return in full above 430px.

   Read off the live markup rather than guessed — my first attempt hid the wrong child:
     stamp = <b>PN</b><span>/OS</span><em class="pnos-stamp-lb">PHONE</em>
     clock = <b>WK 1</b><span>S1 · 1/12</span>
   so the word to drop is the `em`, and `/OS` — the mark itself — stays. Both buttons keep their
   full `aria-label` ("Open your phone — this week's notifications"), so nothing is lost to a
   screen reader; this is a visual truncation only. */
/* Two constraints have to hold together here, and the first attempt traded one for the other:
   `flex:none` cleared the overlap but shrank both end caps to 39px and 42px, back under LAW 1's
   tap floor. So the floor is restated on them, and the width that costs is taken back from the
   tile labels' tracking (.06em → .03em) rather than from their size. Verified both ways at 390px:
   every dock control ≥44px, and every label clear of its neighbours. */
@media (max-width: 430px) {
  .pnos-os-stamp .pnos-stamp-lb,
  .pnos-dock-clock > span { display: none !important; }
  .pnos-os-stamp, .pnos-dock-clock { flex: none !important; min-width: 44px !important; }
  .pnos-tile-lb { font-size: 11px !important; letter-spacing: .03em !important; }
  /* The last ~11px comes from the dock's own side padding (13.65px each side), not from the type.
     Taking it from the gutter rather than the glyphs is the right order of sacrifice: the padding
     was never carrying meaning and the labels are at their floor. */
  .pnos-dock-inner { padding-inline: 8px !important; }
}

/* 6e · CRITICAL GAME STATE. UX_RULES §1: "Critical game state must be instantly legible — never
   faint chrome." The insolvency klaxon is the single most consequential message the game shows —
   it was set at 10px, smaller than the body copy of the screen it interrupts. Its dismiss control
   is raised with it, because a warning you cannot read next to a button you cannot read is two
   failures, not one. */
#pn-klaxon > span { font-size: 12px !important; }
#pn-klaxon > button { font-size: 12px !important; }
#pn-cfo-crisis .cfoX-flag { font-size: 11.5px !important; }
#pn-cfo-crisis .cfoX-hrow i { font-size: 11px !important; }

/* 6f · THE FLOOR CAMS AND THE PIPELINE ROWS — the two densest readouts in the game, and the two
   that leaned hardest on sub-9px mono to fit. Raised to the floor; the density they were
   protecting is preserved by the tracking reduction above, not by shrinking the glyphs. */
.fc-plate, .fc-len { font-size: 11px !important; }
.fc-title { font-size: 11.5px !important; }
.opp-chip, .rfi-mono { font-size: 11px !important; }
.s2-ev .g, .s2-wire-line .g, #s2ScrubGrade { font-size: 11px !important; }

/* Three stragglers that survived the pass above because each is set at a specificity the plain
   class could not reach. Read off the live DOM rather than guessed at, and matched exactly:
   the hero eyebrow carries two classes; the scrub time sits three containers deep; the feed
   avatar initials are inside a nested message row. */
.perf-hero .perf-hero-txt .tac-eyebrow.perf-hero-eyebrow { font-size: 11.5px !important; }
.s2-scrub-read .s2-scrub-events .s2-ev .g { font-size: 11px !important; }
.ft-feed .tmsg .tav { font-size: 11px !important; }

/* 6g · THE PERSISTENT CHROME — the topbar, the HUD strip and the next-move rail.
   These are not one surface's problem: they are drawn on EVERY surface, so each value here was
   counted once per screen in the audit and is the reason the desktop totals ran 13–22 while the
   phone totals were 0–1. The phone hides most of this strip; the desktop shows all of it.

   `CASH`, `REPUTATION`, `CLIENTS`, `WEEK` — the four numbers the whole game is played against —
   were labelled at 7.5px. The player's own name and archetype sat at 8px. Six topbar destinations
   (STORE / CFO / COO / FEED / LEAGUE / SIGN IN) were labelled at 9.5px.

   UX_RULES §15.3 again, and the clearest instance of it in the product: the most permanent and
   most consulted text in the game was the smallest text in the game. Raising it is not decoration,
   it is putting weight where the importance already was. The numbers themselves are untouched —
   the size contrast between a 7.5px label and its large value was the one part of this that WAS
   working, and it survives at 11.5px because the values are far larger still. */
.topbar .stat > span,
.topbar .stat-id > span { font-size: 11.5px !important; letter-spacing: .1em !important; }
.topbar .stat .stat-unit { font-size: 11px !important; }
.topbar .tb-btn > span,
.topbar #account button { font-size: 11.5px !important; }
#pn-nextmove .nm-k { font-size: 11.5px !important; }
#pn-nextmove .nm-go { font-size: 12px !important; }

/* The system's own eyebrow token is 11px (`--pn-micro`, pn-system.css). It was computing 10px on
   the stat cards, so the constitution was losing to a local rule on its own component. Restated
   at the value the system already declares — this is not a new number. */
.pn-card--stat .pn-eyebrow, .mvc-kpi-row .pn-eyebrow { font-size: 11px !important; }
.pv-ringc > span, .pv-radkey > span, .pv-seed-note, .dn-eyebrow { font-size: 11px !important; }
.do-now .dn-main .dn-eyebrow { font-size: 11px !important; }   /* nested one class deeper */

/* 6h · `.linkbtn` — the "→" section links (THE FULL BOARD, ALL NBOS, ALL CLIENTS, MANAGE TEAM).
   34px tall against the 44px floor on desktop. These are the primary means of getting from a hub
   summary into the surface it summarises, so a miss here is a navigation dead-end, not a cosmetic
   one. Padding-led so the label does not move. */
.linkbtn { min-height: 44px !important; display: inline-flex !important; align-items: center !important; }

/* 6i · CONTENT-LEVEL STRAGGLERS, desktop. The chrome above is drawn on every screen; these are
   per-surface and were the remainder once the chrome was lifted. Grouped by what they are rather
   than by which screen they appear on, because the same classes recur across surfaces.

   The two that matter most are the HUD meter verdicts (`NAIL-BITER`, `HOLDING`) at 7.5px and the
   distress line (`DISTRESSED — PAYROLL AT RISK`) at 10.5px. Both are UX_RULES §1's named case:
   "Critical game state must be instantly legible — never faint chrome." A verdict on whether you
   are about to lose the agency is not micro-copy. */
.hud-meter .hm-verdict { font-size: 11.5px !important; }
.hud-meter .hm-top > span { font-size: 11px !important; }
.pv-distress { font-size: 11.5px !important; }

/* Section eyebrows, fold footers and pipeline captions — the mono voice again, same floor. */
.dn-eyebrow, .fold-foot, .pv-pbar-nm small,
.fc-board-k, .fc-rec, .fc-ts, .fc-note,
.nbo-chip, .nbo-tape { font-size: 11px !important; }

/* The season ladder states and the hires strip put their text in bare inner spans, so the class
   above them cannot size it — the same shape of defect as the dock stamps in 6d. */
.sea-rung-state > span, .sea-rung > span,
.tm-strip span, .tm-stat > span, .hires-strip span { font-size: 11px !important; }

/* Tracking comes down as size comes up. Wide tracking is what made these unreadable; leaving it
   at 0.24em while enlarging would just make a bigger unreadable thing and cost horizontal room
   we do not have at 390px. */
.pnos-tile-lb, .sea-plate-tag, .sea-rung-tag,
.tac-eyebrow, .mvc-kpi-lbl, .s2-bk-k, .nbo-bb-k { letter-spacing: .12em !important; }

/* ── LAW 8 · FIXED FURNITURE MUST NOT EAT THE LAST CONTROL ───────────────────────────────────
   UX_RULES §6: "Floating controls must never overlap content." §2: nothing renders under chrome.

   THE DEFECT. Three things are pinned to the bottom of every game surface — the PN/OS dock (66px),
   the REPORT chip (44px at bottom:76px), and on some surfaces a toast. The document scrolls, and
   `body` carries `padding-bottom: 0`. So the bottom ~120px of every page is permanently covered:
   scroll to the end and the last element is still underneath the furniture, with no way to move it
   out. Measured on Hires at 390px, the REPORT chip sits directly on top of `SET IT WITH THE CFO` —
   the surface's primary action — and `elementsFromPoint` at the chip's centre returns the chip
   first, so a tap there hits REPORT, not the CTA.

   This is the same class of bug as the summons pile-up in tools/mobile_audit.js's header: a control
   that is perfectly visible and still not pressable.

   THE FIX is scroll clearance, not repositioning. Moving the chip just moves the problem onto
   whatever it lands on; giving the document somewhere to scroll TO means every control can always
   be brought out from under the furniture. 132px = dock 66 + chip 44 + the 22px the chip already
   floats above the dock. `scroll-padding-bottom` matches it so anchored jumps land clear too.

   Deliberately NOT applied to `.pn-app` or a modal's own scroller: an overlay covers the furniture
   anyway, and padding inside one would open a gap at the bottom of every dialog. */
body { padding-bottom: 132px !important; scroll-padding-bottom: 132px !important; }

/* ── LAW 9 · A STICKY ACTION BAR MUST FULLY OCCLUDE WHAT PASSES UNDER IT ─────────────────────
   UX_RULES §2: "Overlays and modals FULLY occlude or heavily blur what's beneath. No
   double-exposure, ever."

   THE DEFECT. The CFO insolvency modal — the first real decision in the game, which every tester
   will meet in week 1 — pins its two REPLY buttons in a sticky bar over a scrolling list of staff.
   The bar's scrim is `linear-gradient(180deg, rgba(251,248,242,0), #fbf8f2 42%)` (style-01.css
   :10154), so it is fully transparent for its first 42% — and the buttons sit in exactly that
   band. Measured: `.cfoX-acts` overlaps `.cfoX-rows` on load, at 390px, before any scrolling.
   The result is names and salaries reading through the middle of both buttons.

   Confirmed pre-existing, not a side effect of LAW 8: A/B'd with body padding forced to 0, the
   overlap is byte-identical. Worth stating because LAW 8 lands nearby and would otherwise be the
   obvious suspect.

   The scrim is kept — a hard edge across a scrolling list looks worse and the fade is the right
   idea — but it reaches full opacity by 16% instead of 42%, so the controls always sit on solid
   ground while the list still softens as it passes beneath. A rule about occlusion, so it is a law;
   the colour is style-01.css's own value, unchanged. */
.cfoX-mail .cfoX-acts {
  background: linear-gradient(180deg, rgba(251,248,242,0) 0%, #fbf8f2 16%) !important;
}

/* ── LAW 7 · THE WEEKDAY RAIL MEETS THE TAP FLOOR ────────────────────────────────────────────
   UX_RULES / LAW 1. `.s2-day` (MON–FRI on the Floor) measured 38–39px wide against the 44px
   floor — five adjacent targets, all under, which is the arrangement where a near-miss actually
   costs you: miss MON and you get TUE, silently.

   Fixed on the horizontal axis only. The rail is a five-across strip inside a 390px viewport, so
   `min-width:44px` would total 220px plus gaps and could overflow; `flex:1` lets them share the
   full rail width instead, which lands every one of them above the floor with no new horizontal
   scroll. Height was already 42px and is nudged to the floor.

   NOTE ON `.help-chip`: the audit reported it at 15×15, and it is NOT fixed here. Its hit area is
   already expanded to 44px by pn-craft-20260815.css:70-71. The bounding box stays 15px by design,
   which is what a rect-based audit sees — a false positive, recorded so it is not "fixed" twice. */
.s2-days .s2-day, .s2-day { flex: 1 1 0 !important; min-height: 44px !important; }

/* ── LAW 10 · NO ELEMENT MAY PAINT OUTSIDE ITS OWN PARENT IN THE COMMAND BAR ──────────────────
   UX_RULES: occlusion. The fifth appearance of the topbar collision class (CEO-70, -75, -76,
   QA48, and today's store audit, which found the clock chip sitting on "Clients", "Week" and
   "/S1" at both 1440 and 1900).

   IT WAS NEVER THE CLOCK. Measured geometry, 1440:

       DIV.row        x 339→541   (202px, the width flex gave it)
         DIV.hud-group x 339→673  (334px — 132px PAST its own parent)
       SPAN.game-clock x 548→658  (exactly where flex put it, after .row)

   A flex item defaults to `min-width: auto`, so it refuses to shrink below its content width.
   The parent's box collapses to the space available; the child renders at its natural size and
   spills. Nothing is out of flow and nothing is mispositioned — the child is simply painting
   outside the box that is supposed to contain it, and whatever sits in that space wears it.

   That is why four previous fixes did not hold: each one moved, restyled or hid the CLOCK, which
   is the element at the far END of the collision. The overflowing element was never touched.
   `#hud` already carries `min-width:0; overflow:hidden` — someone hit this before and guarded a
   sibling container, not this one.

   The law is stated about containment rather than about the clock, so the next element parked in
   that space does not reopen the ticket. */
.topbar .row,
.topbar .hud-group { min-width: 0 !important; }
/* Let the group reflow inside its parent instead of overflowing it. .row is already
   `flex-wrap: wrap` and 153px tall, so there is room for a second line. */
.topbar .hud-group { flex-wrap: wrap !important; row-gap: 4px !important; }
