/* ══════════════════════════════════════════════════════════════════════════════════════════════
   PN-UX-BLOCKERS · 2026-08-15 — the three CEO blockers + the craft pass on what they touch.
   Source: design/audit-2026-08-15/ (probe_before.json carries the measured baseline).

   WHY ITS OWN FILE: style-01.css is 10.8k lines and script-01.js is 2.3MB. Both are the root
   cause of the regression class this sheet exists to fix. Nothing new goes into either.
   Loaded LAST in play.html so it wins on document order; the two runtime-injected stylesheets
   (account.js PN_IPAD_CSS, PNTest #pn-tester-style) land in <head> AFTER every <link>, so rules
   targeting those are deliberately raised above their specificity — never with !important where
   a real selector will do.

   ART DIRECTION IS UNCHANGED. design/STYLE_SOURCE_OF_TRUTH.md stays locked: burnt-orange #9d4300,
   IS 900, JetBrains Mono, near-square brutalist radius. The CEO's 2026-07-23 WARM BONE light
   theme also stays — it is a decision, not drift, so this sheet fixes the FORM of the auth card
   (radius / shadow / headline), never its palette. apple-design contributes the craft layer only:
   grid discipline, reserved space instead of overlap, 44px targets, measured contrast, restraint.
   /play is a UTILITY surface on apple-design's two-axis test → motion budget stays near-zero.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */


/* ══ BLOCKER 1 ═════════════════════════════════════════════════════════════════════════════════
   "Begin the interview" painted ON TOP of Marlowe's dialogue. UX_RULES §2 (Occlusion Law).

   MEASURED CAUSE (not guessed): at 1280x720 .vc-intro reported clientHeight 102 / scrollHeight
   139 — 37px of the paragraph painted OUTSIDE its own box. .vc-room-body is a fixed-height flex
   column; .vc-intro and .vc-cta-row never declared `flex`, so they inherited the default
   `flex:0 1 auto` and were SHRUNK below their content height. `min-height:5.2em` on .vc-intro —
   there to reserve space for the typewriter so the card does not jump — became the shrink FLOOR
   it collapsed to. Text does not disappear when its box shrinks; it spills, and the next sibling
   is laid out at the shrunken offset, i.e. directly over the spill.

   THE FIX IS THE CAUSE, not the symptom: forbid the shrink. .vc-room-body already scrolls
   (added by the 2026-08-11 Q6 fix), so non-shrinking children simply extend the scroll range —
   every word stays reachable and nothing is ever painted under anything. The reserve is kept as
   a min-height so the typewriter still causes zero layout shift (apple-design-interaction:
   perceived performance — never reflow the page while text is arriving).
   ═════════════════════════════════════════════════════════════════════════════════════════════ */
.vc-room-body > .vc-q,
.vc-room-body > .vc-intro,
.vc-room-body > .vc-cta-row,
.vc-room-body > .vc-beat,
.vc-room-body > .vc-fine{ flex:0 0 auto; }

/* The CTA gets its own real row rather than inheriting whatever the previous block left behind.
   Layout does the spacing (flex + gap), not per-element margins. */
.vc-room-body > .vc-cta-row{
  display:flex; flex-wrap:wrap; align-items:center; gap:12px;
  margin:6px 0 14px;
}
/* 44px is the floor for any primary action (apple-design-interaction / UX_RULES control law).
   .vc-begin measured 40px tall. */
.vc-room-body .vc-begin{ min-height:44px; }

/* The paragraph keeps its no-jump reserve but can now grow past it. */
.vc-room-body > .vc-intro{ min-height:5.2em; }


/* ══ ROOT CAUSE BEHIND BLOCKER 2 ═══════════════════════════════════════════════════════════════
   The consent strip is position:fixed;bottom:0 and ate the foot of every fold.

   script-02.js already publishes the strip's REAL measured height as --pn-consent-h on <html>
   (a ResizeObserver keeps it exact at any width and any copy wrap), and style-01.css already
   spends it on `body.pn-consent-on #app`. But the auth/holding screen is NOT #app — it is
   .pn-stage, a position:fixed;inset:0 layer rendered by account.js. So the reservation simply
   never reached the one screen every new player sees first.

   Rather than add a second magic number, this spends the SAME measured variable on the stage.
   One source of truth for the bar's height; no guessed 96px anywhere.
   ═════════════════════════════════════════════════════════════════════════════════════════════ */
body.pn-consent-on .pn-stage{
  /* mirrors the padding account.js sets on .pn-stage — named here so the geometry below can
     compose with it instead of re-deriving it. */
  --pn-pad:clamp(16px,4vw,60px);
  padding-bottom:calc(var(--pn-pad) + var(--pn-consent-h,0px));
}
/* .pn-tablet is max-height:calc(100% - 2px), and 100% resolves against the stage CONTENT box —
   so the cap above shrinks the device automatically. .pn-screen does NOT follow, because its
   min-height:min(76vh,624px) is a hard floor that ignores the stage entirely: at 720px tall with
   a 75px bar it demanded 547px of a 512px opening and overflowed the device it lives in.
   Clamp it to the real remaining fold. 30px = the tablet's 14px padding either side + its 2px. */
body.pn-consent-on .pn-stage .pn-screen{
  min-height:min(76vh, 624px, calc(100dvh - (var(--pn-pad) * 2) - var(--pn-consent-h,0px) - 30px));
}
/* Same reservation for the CASED (in-game device) variant of the shell, which shares the idiom. */
body.pn-consent-on .pn-hcase{ padding-bottom:var(--pn-consent-h,0px); }

/* The strip yields to the one-overlay-at-a-time rule already established in style-01.css, and
   gains a visible focus ring + an honest reduced-motion posture. */
#pn-consent{ scroll-margin-bottom:12px; }


/* ══ BLOCKER 3 ═════════════════════════════════════════════════════════════════════════════════
   The fixed bottom-left REPORT pill permanently clipped copy.

   MEASURED: at 390x844 with tester mode on, #pn-tester sat at left:12px / bottom:12px and its
   painted box intersected .pnc-acts — the consent strip's Decline/Accept buttons. That is worse
   than a clipped caption: two interactive controls fighting for the same pixels, with the pill
   on top at z-index 21600. In-game it lands on .vc-fine, the interview's caption line.

   TWO PARTS, because there are two distinct collisions:
     1. The pill is lifted above ANY bottom-docked chrome using the same measured
        --pn-consent-h. It never needs to know what that chrome is.
     2. Content columns that can run to the bottom-left reserve a real safe corner, so the last
        line of copy stops short of the pill instead of being painted under it.
   ═════════════════════════════════════════════════════════════════════════════════════════════ */
/* (1) outranks the runtime-injected `#pn-tester{bottom:12px|92px}` without !important:
       `html body.pn-tester-on #pn-tester` = one id + one class + two elements. */
html body.pn-tester-on #pn-tester{
  bottom:calc(12px + var(--pn-consent-h,0px) + env(safe-area-inset-bottom,0px));
}
html body.pn-tester-on.pnos-dock-on #pn-tester{
  bottom:calc(92px + var(--pn-consent-h,0px) + env(safe-area-inset-bottom,0px));
}
/* The interview forces the pill to bottom:10px at <=430px (style-01.css). Keep that intent —
   tight to the edge — but still clear whatever is docked below it. */
@media (max-width:430px){
  html body.pn-tester-on:has(.vc-room) #pn-tester{
    bottom:calc(10px + var(--pn-consent-h,0px) + env(safe-area-inset-bottom,0px));
  }
}
/* (2) the reserved corner = pill height + 12px gap + 10px breathing room, spent only while the
       pill actually exists (body.pn-tester-on).
       ⛔ THIS IS DERIVED FROM THE PILL'S HEIGHT — it is a single token for exactly that reason.
       It was hardcoded 48px against a 26px pill; the a11y pass then raised the pill to the 44px
       target floor (see "TESTER CHIP" below), which would have silently re-opened Blocker 3 —
       the reserve would have been 18px short and the pill would be back on top of .vc-fine.
       One number, derived once. If the pill's height changes again, change it HERE. */
:root{ --pn-tester-h:44px; --pn-tester-reserve:calc(var(--pn-tester-h) + 22px); }
@media (max-width:760px){
  body.pn-tester-on .vc-room-panel{ padding-bottom:calc(22px + var(--pn-tester-reserve)); }
  body.pn-tester-on .vc-room-body{ scroll-padding-bottom:var(--pn-tester-reserve); }
  /* the caption is the line that was being clipped — keep its last line clear of the corner */
  body.pn-tester-on .vc-fine{ padding-bottom:6px; }
  body.pn-tester-on .pn-app{ padding-bottom:calc(clamp(26px,5.6vw,40px) + var(--pn-tester-reserve)); }
}


/* ══ CRAFT · THE AUTH CARD BACK ON REAL TOKENS ═════════════════════════════════════════════════
   The audit's single worst tonal break: a soft-rounded, soft-bevelled card reading as generic
   SaaS inside a brutalist noir game.

   WHAT IS NOT CHANGED: the warm bone palette. That is the CEO's 2026-07-23 call ("light must be
   a premium warm beige — bone / parchment") and it is honoured. The break is not the colour, it
   is the FORM — .lg-panel ships border-radius:16px and a 44px-blur soft elevation, which is the
   opposite of SST §2 ("radius is tiny — near-square, brutalist" + "hard offset shadows").

   Scoped to .pn-authwin ONLY. .lg-panel is the shared Finder-glass card used across the product;
   repainting it globally would be a restyle, not a fix, and is not what was asked for.
   ═════════════════════════════════════════════════════════════════════════════════════════════ */
.pn-authwin.lg-panel{
  border-radius:3px;                     /* the .lg-btn brutalist base radius — one geometry */
  /* THE CLIP — the chamfered top-right silhouette the rest of the system carries, at panel scale. */
  clip-path:polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%);
  /* HARD OFFSET SHADOW (SST §2 motif), not a soft bevel.
     ⛔ IT MUST BE A FILTER, NOT A box-shadow. clip-path clips the element's box-shadow along with
     everything else, so the first version of this rule painted a 10px offset slab that was then
     clipped entirely away — getComputedStyle reported it present and the screen showed nothing.
     (Second time in this same pass that computed style lied; see the hero-italic note below.)
     filter:drop-shadow() is applied AFTER clipping, so it traces the CHAMFERED silhouette — which
     is both visible and more correct. It is what .lg-btn already does via --lg-shadow.
     Ink only: the accent already carries three roles on this card (eyebrow, active-tab underline,
     primary button fill). A fourth, purely decorative orange slab would break the SST §5e accent
     discipline, so the orange register mark is deliberately NOT here. */
  filter:drop-shadow(10px 10px 0 rgba(11,28,48,.16));
  box-shadow:0 0 0 1px rgba(11,28,48,.22);
}
:is(.pn-stage,.pn-hcase):not(.is-light) .pn-authwin.lg-panel{
  filter:drop-shadow(10px 10px 0 rgba(4,7,12,.6));
  box-shadow:0 0 0 1px rgba(255,255,255,.10);
}
.pn-authwin.lg-panel > .lg-titlebar{ border-radius:2px 2px 0 0; }

/* The FRAME was brutalist while its CONTENTS stayed default-SaaS, which made the mismatch louder
   than before the fix. .lg-btn is already on the 3px + chamfer geometry, but .lg-field ships
   border-radius:9px — so the email/password inputs were the soft-cornered controls still reading
   as a generic form. Brought onto the same geometry, scoped to the auth window only (.lg-field is
   shared across the product). */
.pn-authwin .lg-field{ border-radius:3px; }
.pn-authwin .lg-field:focus-visible{ outline:2px solid #f97316; outline-offset:2px; }

/* The headline commits. SST display type is uppercase + ultra-tight; IS 900 is the face.
   24px/normal-case read as a SaaS card title; this is a display moment. */
.pn-authwin .pn-title{
  font:italic 900 clamp(26px,3.1vw,34px)/.96 IS,'Segoe UI',Roboto,Arial,sans-serif;
  font-synthesis:style;
  text-transform:uppercase;
  letter-spacing:-.04em;
  text-wrap:balance;
}
/* One accent, disciplined: the eyebrow is mono/tactical, the headline is ink. */
.pn-authwin .pn-sub{ max-width:36ch; }

/* ── THE SIGN IN / SIGN UP RAIL — a class-name collision, and the visual heart of "generic SaaS"
   The auth screen renders a big grey rounded capsule with an orange pill inside it. account.js
   never asked for that; it documents the opposite intent ("the lit tab carries the accent
   underline rather than a filled slab, so it reads as 'you are here' and never competes with the
   primary button below it") and styles .pn-tabs as a 2-column underline grid.

   The collision: SYSTEM_V2 (pn-system.css) owns a GLOBAL `.pn-tabs`/`.pn-tab` nav-pill component
   — `background:var(--track)`, `border-radius:var(--mvc-pill)`, `padding:4px`, and
   `.pn-tab[aria-selected="true"]{background:var(--p)}`. Two different components, one class name.
   PN_IPAD_CSS loads later so it wins where the two overlap — but it only ever sets display,
   grid-template-columns, gap, margin and border-BOTTOM. Every property it does not mention
   (background, border-radius, padding, the other three borders, and the selected pill fill at
   0-2-0 specificity) survives from SYSTEM_V2. That residue IS the capsule.

   Fixed by neutralising the residue, scoped to the auth surfaces only. The global SYSTEM_V2 pill
   is used across the product and is NOT touched. Specificity is raised above both sheets so the
   result does not depend on load order. */
:is(.pn-stage,.pn-hcase) .pn-tabs{
  background:none; border:0; border-radius:0; padding:0;
  border-bottom:1px solid rgba(255,255,255,.16);
}
:is(.pn-stage,.pn-hcase).is-light .pn-tabs{ border-bottom-color:rgba(20,16,12,.18); }
:is(.pn-stage,.pn-hcase) .pn-tab{
  border-radius:0; background:none; padding:10px 8px;
  border-bottom:2px solid transparent;
}
/* the "you are here" state is the accent UNDERLINE — one accent, one role (SST §5f) */
:is(.pn-stage,.pn-hcase) .pn-tab[aria-selected="true"],
:is(.pn-stage,.pn-hcase) .pn-tab.is-on{
  background:none; color:#fff; border-bottom-color:#f97316;
}
:is(.pn-stage,.pn-hcase).is-light .pn-tab[aria-selected="true"],
:is(.pn-stage,.pn-hcase).is-light .pn-tab.is-on{
  color:#241f1b; border-bottom-color:#b4380d;   /* AA burnt-orange on bone (SST §5f corollary) */
}
/* THE INACTIVE TAB LABEL — WCAG 1.4.3, and it is NOT large text.
   "Sign up" is 12px at weight 800. WCAG's large-text allowance (3:1) needs 18.66px AND bold, or
   24px; 12px/800 is bold but nowhere near 18.66px, so the floor is the full 4.5:1. account.js
   set rgba(36,31,27,.55), which measured 3.53:1 on painted pixels against the bone card — a
   fail, on the control that tells a new player account creation exists at all.
   .68 measures 4.76:1. It stays clearly quieter than the lit tab (#241f1b, 13.4:1), so the
   "you are here" hierarchy the tab rail was rebuilt for is preserved — this buys legibility with
   alpha, not with a second accent.
   Specificity must beat account.js's own `:is(.pn-stage,.pn-hcase).is-light .pn-tab` (0,3,0) —
   `:is(…)` takes the weight of its heaviest argument, so :not(.is-on) here makes it (0,4,0). */
:is(.pn-stage,.pn-hcase).is-light .pn-tab:not(.is-on){ color:rgba(36,31,27,.68); }
/* Dark passed at 5.57:1 but sat close to the floor on the same 12px glyphs; .78 → 6.6:1.
   Same reasoning, same restraint — no colour introduced, only alpha. */
:is(.pn-stage,.pn-hcase):not(.is-light) .pn-tab:not(.is-on){ color:rgba(255,255,255,.78); }

/* The offline door is now a peer of Google (see account.js) — give it peer geometry rather than
   the footnote it used to be, and keep it visibly SECONDARY to the primary path. */
/* .lg-btn--ghost is background:transparent + border-color:transparent, i.e. no chrome at all — as a
   footnote under a form that was fine, but as a PEER of the boxed Google button it read as a bare
   caption rather than a control. Given real ghost chrome: same geometry as its peer, visibly
   secondary to it (hairline + no fill, against Google's filled secondary). */
.pn-authwin .pn-offline{
  align-self:stretch; width:100%; margin-top:10px;
  justify-content:center;
  min-height:44px;
  border:1px solid var(--lg-sec-border, rgba(255,255,255,.18));
  border-radius:3px;
}
.pn-authwin .pn-offline:hover{
  border-color:var(--lg-orange,#f97316);
}


/* ══ CRAFT · MEASURED CONTRAST ═════════════════════════════════════════════════════════════════
   Measured with a real relative-luminance calculation against the painted backdrop
   (#0a0f18 — .vc-backdrop), not eyeballed. Baselines in probe_before.json.
   ═════════════════════════════════════════════════════════════════════════════════════════════ */
/* THE PROGRESS-DOT RAIL. Idle dots were rgba(255,255,255,.16) = 1.57:1 — a FAIL against the
   3:1 floor for non-text UI that carries meaning (WCAG 1.4.11). These dots encode how far
   through the interview you are, so they are information, not decoration.
   .42 => ~3.6:1 (idle), .72 => ~9.5:1 (done). State is still carried by WIDTH as well as
   value (.on is 22px vs 14px), so it is never colour alone. */
.vc-dot{ background:rgba(255,255,255,.42); }
.vc-dot.done{ background:rgba(255,255,255,.72); }

/* ══ CRAFT · THE HERO ACTUALLY RENDERS ITALIC ══════════════════════════════════════════════════
   SST §2: display type is IS 900, HUGE, italic, uppercase, ultra-tight. "DO YOU HAVE / WHAT IT
   TAKES?" was upright on screen even though .vc-q--hero already declared font-style:italic.

   WHY (and why a computed-style check does NOT catch it): the rule sets
   `font-family: var(--mvc-disp, …)`, and --mvc-disp resolves to 'Space Grotesk' on the default
   ONYX theme. Space Grotesk is self-hosted by mvc-os.css as TWO @font-face rules and BOTH are
   `font-style:normal`. The family matches, the normal face is selected, and the text paints
   upright — while getComputedStyle still cheerfully reports `italic`, because computed style is
   what was ASKED FOR, not what was PAINTED. The first pass of this fix "verified" it that way
   and was wrong; the raster check in tools/ux_blocker_probe.mjs now proves it by pixels.

   The fix is the SST's own answer: IS 900 italic — and inter-900-i.woff2 is ALREADY
   self-hosted and declared `font-weight:800 900; font-style:italic` in pn-system.css. A real
   italic file, sitting unused. Theme packs still own this headline's COLOUR through .vc-hl →
   var(--accent), so nothing loses its skin. font-synthesis is a backstop for any future theme
   that swaps the face back to a normal-only family. */
.vc-q--hero{
  font-family:IS,'Segoe UI',Roboto,Arial,sans-serif;
  font-weight:900;
  font-style:italic;
  font-synthesis:style;
  letter-spacing:-.04em;
}

/* THE CAPTION. "Eight questions. No skip…" measured 5.4:1 at 11.5px — it passes AA, but it is
   the line that tells a player the interview cannot be re-rolled, and it was set at the timid
   end of the scale. Raised to ~7.6:1 and 12px: comfortably legible, still clearly secondary. */
.vc-room-body .vc-fine{
  font-size:12px;
  color:rgba(232,240,251,.78);
}
.vc-room-body .vc-fine i{ color:rgba(240,246,255,.92); }


/* ══ FOCUS · the craft layer's non-negotiable ══════════════════════════════════════════════════
   Every control this sheet touches keeps a visible, high-contrast focus ring (apple-design-tactics).
   ═════════════════════════════════════════════════════════════════════════════════════════════ */
.vc-begin:focus-visible,
.vc-ans:focus-visible{
  outline:2px solid #ff9a5f; outline-offset:2px;
}

/* ══ A11Y · THE FOCUS RING ON GLASS BUTTONS ACTUALLY PAINTS ════════════════════════════════════
   WCAG 2.1 AA 2.4.7 (Focus Visible) + 1.4.11 (Non-text Contrast, 3:1 floor).

   THE AUDIT MIS-DIAGNOSED THIS ONE, AND THE PIXELS SAY SO. It reported #au-offline's ring as
   "1.89:1 in light theme, fine in dark at ~7.8:1" and prescribed a colour change to #b4380d.
   Measured against PAINTED PIXELS instead of computed style
   (tools/a11y_probe_20260815.mjs, a11y_before.json):

       #au-offline ring vs card    light  1.01:1      dark  1.00:1
       #au-google  ring vs fill    light  1.17:1      dark  9.86:1

   1.00:1 is not a dim ring. It is NO RING AT ALL — in BOTH themes. Recolouring it would have
   shipped a ring that still never rendered, and closed the ticket.

   THE CAUSE is the trap this very sheet already documents twice (the panel's clipped-away
   box-shadow above; the "italic" headline that painted upright below). `.lg-btn` carries
   `clip-path:polygon(…)` for its chamfered silhouette — pn-glass.css:221, and its own comment at
   :203 says "clip-path also clips box-shadow". It clips the OUTLINE too. So
   `outline:2px solid #ff9a5f; outline-offset:2px` on a .lg-btn is painted entirely outside the
   clip region and discarded. getComputedStyle still reports `outlineColor: rgb(255,154,95)` and
   `el.matches(':focus-visible')` still returns true — both were true in the before-run, on a
   button with a visibly bare edge. THIRD time computed style has lied in this file. Measure paint.

   THE FIX is the one pn-glass.css already reached for on .lg-btn: an INSET ring, which is drawn
   inside the clip region and survives. The remaining defect is that the inset ring was hardcoded
   `#fff` — correct on dark glass, invisible on porcelain (1.17:1).

   SCOPE — COMPONENT LEVEL, NOT SCOPED TO .pn-authwin. Stated because the brief asked which:
   `.lg-btn` is the shared glass button and `.lg-light` is its documented light-theme hook
   (pn-glass.css:23 "Add class .lg-light to any .lg-panel"). A ring that vanishes on porcelain is
   the same 2.4.7 failure on EVERY light glass surface in the product, not just this card;
   scoping the fix to the auth window would knowingly leave the rest failing. The change is also
   purely additive — it introduces a token, changes no dark-theme value, and touches no palette,
   geometry or motion. Art direction (STYLE_SOURCE_OF_TRUTH.md) is untouched.

   WHY THE RING COLOUR FOLLOWS THE BUTTON, NOT THE PAGE: --lg-focus-ring must contrast with the
   fill it sits ON. .lg-btn--primary and .lg-btn--danger keep dark saturated fills in BOTH themes,
   so they keep the white ring; only the light-fill variants flip to ink-navy. Keying this to the
   page theme alone would have put #0b1c30 on top of #9d4300 — 1.9:1, a new failure. */
.lg-btn:focus-visible{
  box-shadow:inset 0 0 0 2px var(--lg-focus-ring,#fff), var(--lg-inset, none);
}
/* ⛔ AND THE SECOND BUG UNDER THE FIRST — why #au-offline stayed at 1.01:1 in BOTH themes even
   after the ring was themed, while #au-google (same component, same rule) jumped to 14.66:1.

   `.lg-btn--ghost` declares `--lg-inset:none` (pn-glass.css:341) to say "this variant has no
   inner shadow". The focus rule then composes `box-shadow: inset 0 0 0 2px <ring>, none` — and
   `none` is NOT a legal ITEM in a box-shadow list. That makes the declaration invalid at
   computed-value time, which does not fall back to the previous rule: it resolves to the
   property's initial value, `none`. The whole ring, silently deleted by its own companion token.
   getComputedStyle on the focused ghost button reported `box-shadow: "none"` while
   `:focus-visible` matched — which is exactly how this shipped unnoticed.

   THIS IS NOT NEW: pn-glass.css:249 already composed the ring the same way, so EVERY ghost button
   in the product has had an invisible focus ring since the component was written, in dark theme
   as well as light. The audit's "dark is fine at ~7.8:1" was reading computed style, not paint.

   Fixed at the cause rather than per-variant: `--lg-inset` becomes a VALID no-op shadow instead
   of the invalid keyword. `inset 0 0 0 0 transparent` paints nothing — zero spread, zero blur,
   fully transparent — so the ghost's resting appearance is byte-identical, but it now composes
   into a shadow list instead of destroying it. Any future variant that wants "no inset" should
   use this value, not `none`. */
.lg-btn--ghost{ --lg-inset:inset 0 0 0 0 transparent; }
/* porcelain: the ring becomes the SST on-surface navy-ink (--lg-ink-slab, #0b1c30) */
.lg-light{ --lg-focus-ring:#0b1c30; }
/* …except on the variants whose own fill stays dark in light theme — they keep white. */
.lg-light .lg-btn--primary,
.lg-light .lg-btn--danger{ --lg-focus-ring:#fff; }

@media (prefers-reduced-motion:reduce){
  .vc-dot{ transition:none; }
}


/* ══ A11Y · TESTER CHIP HIT TARGET ═════════════════════════════════════════════════════════════
   WCAG 2.1 AA 2.5.5 / apple-design-tactics 44pt floor — the same floor .vc-begin and .pn-offline
   were both raised to earlier in this sheet.

   MEASURED: 90x26 at 390px, 230x26 at 1280px. 26px against a 44px floor, and it is the ONLY
   control in this pass that was left short. It is built from `padding:7px 12px` on a 10px/1 mono
   label in the runtime-injected sheet (script-01.js), i.e. 10 + 14 + 2px border = 26.

   RAISED, NOT EXCUSED — deliberately, and here is the reasoning, since the brief offered both:
   this is not a developer-only affordance. It is the REPORT button that ten real testers on real
   phones are being asked to press this week to file feedback, and Blocker 3 above exists because
   this same pill was landing on top of the consent strip's Decline/Accept at 390px. A 26px target
   sitting next to other controls is precisely the mis-tap geometry 2.5.5 is about. A debug
   affordance nobody but us touches would be a fair exception; this one is on the critical path of
   the week's actual objective, so it meets the floor like everything else.

   Height only — the label, colours, position and the panel it opens are untouched. Nothing here
   goes into script-01.js; this outranks the injected `#pn-tester-chip` (0,1,0) with
   `html body #pn-tester-chip` (0,1,2), no !important, same idiom as Blocker 3 above. */
html body #pn-tester-chip{
  min-height:var(--pn-tester-h,44px);
  box-sizing:border-box;
}


/* ══ A11Y · REDUCED MOTION REACHES THE VIDEO ═══════════════════════════════════════════════════
   WCAG 2.1 AA 2.2.2 (Pause, Stop, Hide) — auto-playing motion over 5s needs a way to stop it.

   Every CSS-driven animation on this surface already resolves correctly under
   `prefers-reduced-motion: reduce`. The gap was the one piece of motion CSS cannot reach: the
   native <video id="vc-loop" autoplay loop muted> behind Marlowe's interview. MEASURED with the
   media feature emulated: `paused:false`, currentTime advancing — a looping human face moving
   for the entire interview, for a user who has asked the OS for no motion.

   Two halves, because the element fights back. This is the CSS half: script-01.js's `playing`
   handler sets `.vc-room-still{opacity:0}` as an INLINE style to cross-fade the poster out, and
   an inline style beats a stylesheet — so the still is pinned back with !important, which is the
   one thing that can outrank it. The JS half (pausing the element, and keeping it paused against
   a `canplay` handler that re-kicks it) is in pn-a11y-20260815.js — CSS cannot pause a video.
   The still is the SAME frame the video already ships as its poster, so the scene is unchanged:
   Marlowe is still there, she simply stops moving. */
@media (prefers-reduced-motion:reduce){
  .vc-room-still{ opacity:1 !important; }
  #vc-loop{ visibility:hidden; }     /* the still sits beneath it — reveal it, don't blank the frame */
}

/* ══ THE LOGIN CARD: NO ORANGE STROKE, AND A QUIETER TAB ROW (CEO, 2026-09-20) ═══════════════
   "lose the orange stroke and make this more elegant - the sign up looks like a tab - its not -
   its an external button link so make it so."

   ⛔ THE ORANGE STROKE WAS A FOCUS RING, not a border. pnTrapModal() focuses the dialog itself on
   open, so the browser painted the focus outline around the whole card - on a screen nobody had
   touched yet. A focus ring is feedback for a person who moved focus; a ring drawn because a
   SCRIPT moved it tells the player nothing and, at panel scale, reads as a decorative frame the
   rest of the art direction does not have. Removed on the container only. Every real control
   keeps its ring, which is where the ring earns its place. */
.pn-authwin[role="dialog"]:focus,
.pn-authwin[role="dialog"]:focus-visible{ outline:none !important; box-shadow:0 0 0 1px rgba(255,255,255,.10) !important; }

/* With Sign up gone from the row, one lone "tab" is just a heading with an underline. Quieter:
   the label stays as the section marker it now is, and the accent underline goes - the card
   already carries the accent on its primary button, and SST §5e caps how many roles it gets. */
.pn-authwin .pn-tabs{ border-bottom:1px solid rgba(255,255,255,.10); gap:0; }
.pn-authwin .pn-tab.is-on{ box-shadow:none !important; border-bottom:0 !important; }

/* The way OUT of this form reads as a way out: full width, ghost, under the note that explains
   it - not a peer of LOG IN, which is the thing this screen is for. */
.pn-authwin .pn-signup-out{ width:100%; margin-top:10px; justify-content:center; }
/* ⛔ CENTRE IT UNDER THE BUTTON IT BELONGS TO (CEO, 2026-09-20): "Center forgot password button
   below main button." It was floating hard right, level with nothing, reading as a stray control
   rather than the quiet second option under LOG IN. Centred, narrowed and set below the primary
   so the eye goes LOG IN first and finds this only if it needs it. */
.pn-authwin .pn-forgot{ display:flex; margin:12px auto 0; justify-content:center; }
