/* ============================================================
 * Project Pleasant — page layer (the app, not the components).
 * Component chrome lives in Tide canon (tide.css: c29-sky,
 * c29-channel, c29-orb, c29-clock, shelf, sheet, lock, pointer).
 * What lives here: the lock state, and the little living scenes
 * inside the tiles — one bold sketch per surface.
 * ============================================================ */

/* while locked, the house is politely out of focus behind the card */
.pl-stage.pl-locked .pl-main, .pl-stage.pl-locked .pl-shelf { visibility: hidden; }

/* settings replace the grid (the shelf and the sky stay) */
.pl-stage.pl-sheet-open .pl-main { visibility: hidden; }

/* search replaces the grid the same way */
.pl-stage.pl-search-open .pl-main { visibility: hidden; }

/* ---- the folder: a room inside the house, same geometry manners -- */
.pl-stage.pl-folder-open .pl-main { visibility: hidden; }
.pl-folder { position: absolute; inset: 0 0 calc(88px + var(--safe-b)) 0; z-index: 6; display: flex; flex-direction: column;
  align-items: center; padding: calc(14px + var(--safe-t)) 14px calc(12px + var(--safe-b)); }
.pl-folder[hidden] { display: none; }
.pl-folder:not([hidden]) { animation: pl-rise var(--d-sheet) var(--ease) both; }
.pl-folder-head { display: flex; align-items: center; gap: 14px; width: min(1060px, 100%); }
.pl-folder-title { font-size: 24px; font-weight: 700; color: var(--ink); letter-spacing: -.01em; }
.pl-folder-sub { font-size: 14.5px; color: var(--ink-2); }
.pl-folder-grid { display: grid; gap: clamp(10px, 1.9vmin, 24px); width: min(1060px, 100%); margin: auto;
  grid-template-columns: repeat(auto-fit, minmax(0, calc((1060px - 3 * clamp(10px, 1.9vmin, 24px)) / 4)));
  justify-content: center; }
@media (max-width: 700px) and (orientation: portrait) {
  .pl-folder-grid { grid-template-columns: repeat(2, 1fr); justify-content: stretch; }
}

/* ---------- tile scenes (shared stage: viewBox 0 0 200 116) ---------- */
.pl-tile-preview svg text { font-family: var(--font-display); }

/* Listen — equaliser bars */
.sc-eq rect { transform-box: fill-box; transform-origin: 50% 100%; animation: pl-eq calc(1.05s / var(--speed)) ease-in-out infinite alternate; }
.sc-eq rect:nth-child(3) { animation-delay: -.3s; } .sc-eq rect:nth-child(4) { animation-delay: -.65s; }
.sc-eq rect:nth-child(5) { animation-delay: -.15s; } .sc-eq rect:nth-child(6) { animation-delay: -.8s; }
.sc-eq rect:nth-child(7) { animation-delay: -.45s; }
@keyframes pl-eq { from { transform: scaleY(.35); } to { transform: scaleY(1); } }

/* Flows — the travelling pulse rides SMIL in the markup; nodes breathe */
.sc-nodes .nd { transform-box: fill-box; transform-origin: center; animation: pl-breathe calc(3.6s / var(--speed)) ease-in-out infinite; }
.sc-nodes .nd.d2 { animation-delay: -1.2s; } .sc-nodes .nd.d3 { animation-delay: -2.3s; }

/* Project X — the breathing orb */
.sc-breathe { transform-box: fill-box; transform-origin: center; animation: pl-breathe calc(4.6s / var(--speed)) ease-in-out infinite; }
@keyframes pl-breathe { 0%, 100% { transform: scale(.84); } 50% { transform: scale(1.04); } }

/* Command Center — the pulse line draws itself along */
.sc-dash { stroke-dasharray: 7 9; animation: pl-dash calc(1.4s / var(--speed)) linear infinite; }
@keyframes pl-dash { to { stroke-dashoffset: -32; } }

/* Tide — waves sliding past each other */
.sc-waves .wv { animation: pl-wave calc(6s / var(--speed)) linear infinite; }
.sc-waves .wv.b { animation-duration: calc(9s / var(--speed)); animation-direction: reverse; }
@keyframes pl-wave { from { transform: translateX(0); } to { transform: translateX(-40px); } }

/* Fleet — the radar sweep */
/* the Flows pulse travels by CSS offset-path, never SMIL — CSS
   animations are exactly what the canon motion gate can stop, so
   reduced motion truly stills this tile (adversary R1 SEV-2) */
.sc-nodes .pulse { offset-path: path("M30 80 C 70 18, 130 98, 170 34"); offset-rotate: 0deg;
  animation: pl-travel calc(3.4s / var(--speed)) linear infinite; }
@keyframes pl-travel { from { offset-distance: 0%; } to { offset-distance: 100%; } }

/* Desk — the top card's check pops gently */
.pl-tile-preview .pop { transform-box: fill-box; transform-origin: center; animation: pl-breathe calc(3.2s / var(--speed)) ease-in-out infinite; }

/* scene captions are a wide-screen enrichment; at phone width the label
   scrim owns the bottom of the art, so the captions stand down */
@media (max-width: 700px) and (orientation: portrait) {
  .sc-cap { display: none; }
}

/* settings sheet: one fixed control column, the back orb at panel size */
.pl-sheet c29-seg { flex: 0 0 168px; }
.pl-sheet c29-seg button { flex: 1; }
#orbBack .pl-orb { width: 44px; height: 44px; }
@media (max-width: 560px) {
  .pl-row { flex-wrap: wrap; }
  .pl-row c29-seg { margin-left: auto; }
  /* P-SET-1 (W4, 2026-10-22): Settings rows get a phone posture — the
     label takes the full width and the control stacks beneath it,
     contained. The desktop fixed 168px control column squeezed labels
     into one-word columns (rig-measured on the pre-fix bytes:
     "Weather in the world" text at 23px wide, name 95px tall) and
     pushed wide segs off the panel's right edge (Ambience bed seg
     388px in a 362px panel, +51px bleed, one button off-panel).
     Scoped to #plSheet only: every other room keeps its row geometry.
     Segs stay a single row (the canon seg thumb tracks one row);
     long option labels wrap inside their own pill, never the seg. */
  #plSheet .pl-row { flex-direction: column; align-items: stretch; gap: 8px; }
  #plSheet .pl-row .pl-row-text { flex: none; width: 100%; }
  #plSheet .pl-row c29-seg { flex: none; width: 100%; margin-left: 0; }
  #plSheet .pl-row c29-seg button { white-space: normal; text-align: center; line-height: 1.15; padding: 4px 6px; }
  #plSheet .pl-row > button { align-self: flex-start; }
}

/* ---- R6: live squares ---- */
/* the Daily Note place replaces the grid like the other sheets */
.pl-stage.pl-note-open .pl-main, .pl-stage.pl-assist-open .pl-main { visibility: hidden; }
.pl-note .pl-panel { overflow-y: auto; max-height: calc(100dvh - 168px); touch-action: pan-y; overscroll-behavior: contain; } /* D5 scroll contract */
/* the room subtitle sits bare on the sky inside .pl-sheet-head (not on
   the panel face), so the soft ink failed there: --pl-ink-soft #2E5A74
   on the sky band #79BFED measured 3.70:1 (Principal-Proof gate, r12).
   It carries the full ink instead — the same pair the room title
   already passes with (#14384C on the band ≈ 6.2:1; dark ≈ 16:1). */
.pl-note-when { font-size: 14.5px; color: var(--pl-ink); font-weight: 600; }
.pl-note-sec { font-size: 12px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--pl-tile-ink-soft); margin: 20px 0 8px; }
.pl-note-sec:first-child { margin-top: 0; }
.pl-note-sample { background: var(--pl-sky-wash); /* D5 (night loop 2026-10-24): the sky-wash fallback class is CLOSED — P4 defined --pl-sky-wash in tokens.css (computed on the Principal stage in both engines, both themes, D5-verified), so the old rgba(255,255,255,.4x) fallbacks were inert in effect but remained a loaded trap for any surface that ever loads app.css without tokens.css. All 13 fallback sites in this file now read the bare token: if the token is ever missing the ground is transparent (the panel shows through — a passing ground) instead of a 40% white wash (the D4 failure). */ border: 1px solid var(--edge-soft);
  border-radius: 14px; padding: 12px 14px; font-size: 14px; line-height: 1.5; white-space: pre-line; }
.pl-note-sample .pl-note-meta { display: block; margin-top: 8px; font-size: 12px; font-weight: 600;
  color: var(--pl-tile-ink-soft); white-space: normal; }
.pl-note-ta { width: 100%; box-sizing: border-box; font: inherit; font-size: 14px; line-height: 1.5;
  color: var(--pl-tile-ink); background: var(--pl-tile-face); border: 1px solid var(--edge-soft);
  border-radius: 12px; padding: 10px 12px; resize: vertical; }
.pl-note-btn { font: inherit; font-weight: 700; font-size: 14px; min-height: 44px; padding: 8px 16px;
  border-radius: 999px; border: 1px solid color-mix(in srgb, var(--pl-tile-ink) 16%, transparent); background: var(--pl-tile-face); /* F5 (Golden Hour fix 2026-10-25): the rim is derived from the button's own ink token. It was var(--edge-soft) — the daylight register's sand-300 at 80% in light — which printed as a stray tan outline on the white tile face (Victor's Golden Hour screenshot; computed rgb(226,214,192)/.8, both engines). The tile family's own rim is a white top-light edge for tiles on the sky and renders invisible for a button sitting on the room card, so the hairline is mixed from the paired ink instead: on-palette in every theme and brand stage by construction, the same derivation style as the register's own edges in tokens.css. */
  color: var(--pl-tile-ink); cursor: pointer; }
a.pl-note-btn { display: inline-flex; align-items: center; justify-content: center; } /* P8 (night loop 2026-10-25): the class sets min-height:44px but no display — an <a> wearing it stays inline, where min-height does not apply, and rendered 79x37 in the Market room (P8 enum rig, both engines; 7 links). Anchors now take the inline-flex button box; <button> hosts keep their UA inline-block and are untouched. */
.pl-note-btn.primary { background: var(--pl-tile-ink); color: var(--pl-tile-face); border-color: transparent; }
.pl-note-btn:disabled { opacity: .45; cursor: default; }
.pl-note-vrow { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--edge-soft); }
.pl-note-vrow:last-child { border-bottom: 0; }
.pl-note-vmain { flex: 1; min-width: 0; }
.pl-note-vsum { font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-note-vmeta { font-size: 12px; color: var(--pl-tile-ink-soft); }
.pl-note-vrow .pl-note-btn { min-height: 40px; font-size: 13px; padding: 6px 12px; flex: 0 0 auto; }
.pl-note-group { font-size: 12px; font-weight: 700; color: var(--pl-tile-ink-soft); margin: 12px 0 2px; }
.pl-note-preview { margin-top: 10px; }

/* the live weather line under the clock — quiet, same ink family as the date */
.pl-clock-sub { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-align: center;
  color: var(--pl-ink-soft); margin-top: 1px; min-height: 13px; }

/* the Assistants place: connection points with honest states */
.pl-assist-block { padding: 13px 0 15px; border-bottom: 1px solid var(--edge-soft); }
.pl-assist-block:last-child { border-bottom: 0; }
.pl-assist-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.pl-conn { flex: none; font-weight: 800; font-size: 11px; letter-spacing: .02em;
  padding: 5px 10px; border-radius: 99px; margin-top: 2px; }
.pl-conn-on { background: #E2F4E7; color: #14663A; }
.pl-conn-gated { background: #FCF0DA; color: #8F5E06; }
.pl-conn-off { background: #E8EDF2; color: #54687B; }
.pl-assist-blurb { margin: 8px 0 0; font-size: 14px; line-height: 1.5; color: var(--pl-ink); }
.pl-assist-gate { margin: 7px 0 0; font-size: 13px; line-height: 1.5; color: var(--pl-ink-soft); }

/* the Daily Note tile's schedule chip lives inside its scene art */
.sc-chip-rect { fill: #223140; opacity: .82; }
.sc-chip-text { fill: #FFF; font-weight: 700; }

/* ---- SAMPLE-WAVE: the sample apps' place + games ---- */
.pl-stage.pl-wave-open .pl-main { visibility: hidden; }
.wv-big { font-size: 30px; font-weight: 800; letter-spacing: -.01em; color: var(--pl-tile-ink); }
.wv-warn { background: rgba(244, 96, 54, .10); border-color: rgba(244, 96, 54, .45); font-weight: 600; }
.wv-beachrow { flex-wrap: wrap; gap: 8px; }
.wv-beachrow .pl-note-btn { min-height: 40px; }
.wv-chart svg, .wv-moon svg { display: block; width: 100%; height: auto; }
.wv-moon { max-width: 430px; margin: 0 auto; }
.wv-stats { gap: 8px; flex-wrap: wrap; }
.wv-stat { font-weight: 800; font-size: 13px; padding: 6px 12px; border-radius: 99px;
  background: var(--pl-sky-wash); border: 1px solid var(--edge-soft); color: var(--pl-tile-ink); }
.wv-stage { display: block; width: 100%; padding: 0; margin: 4px 0 10px; cursor: pointer;
  border: 1px solid var(--edge-soft); border-radius: 16px; overflow: hidden; background: var(--pl-tile-face);
  touch-action: none; -webkit-user-select: none; user-select: none; }
.wv-stage svg { display: block; width: 100%; height: auto; }
.wv-stage:focus-visible { outline: 3px solid var(--pl-tile-ink); outline-offset: 2px; }

/* ================= R7 — the eternal shell ================= */
/* sheet/place entrances get a real motion moment (P-4): a spring
   settle in the house's motion language; reduced motion stands it
   down via the canon gate below. */
.pl-sheet:not([hidden]), .pl-folder:not([hidden]) { animation: pl-sheet-in calc(430ms / var(--speed)) cubic-bezier(.21,1.24,.36,1) both; }
@keyframes pl-sheet-in { from { opacity: 0; transform: translateY(16px) scale(.988); } 62% { opacity: 1; transform: translateY(-3px) scale(1.002); } to { opacity: 1; transform: none; } }
html[data-motion="reduced"] .pl-sheet:not([hidden]), html[data-motion="reduced"] .pl-folder:not([hidden]) { animation: none; }
.pl-stage.pl-place-open .pl-main { visibility: hidden; }
.pl-note-panel { overscroll-behavior: contain; touch-action: pan-y; } /* D5 scroll contract: no -webkit-overflow-scrolling (see tide.css .pl-sheet) */

/* the top strip (M-1): optional, dismissible, absent when empty */
.pl-topstrip { position: relative; z-index: 7; width: min(1060px, calc(100% - 20px)); margin: calc(8px + var(--safe-t)) auto 0;
  display: flex; align-items: center; gap: 10px;
  background: var(--pl-tile-face); color: var(--pl-tile-ink); border: 1px solid var(--edge-soft);
  border-radius: 14px; padding: 9px 12px; font-size: 13.5px; font-weight: 600;
  box-shadow: 0 8px 24px rgba(20,40,60,.14); }
.pl-topstrip[hidden] { display: none; }
.pl-topstrip .grow { flex: 1; min-width: 0; }
.pl-topstrip button { flex: none; }

/* favorites bar + the unmistakable filtered state (S-1) */
.pl-favbar { display: flex; gap: 8px; justify-content: center; padding: 2px 0 8px; }
.pl-favbtn { font: inherit; font-size: 13px; font-weight: 700; min-height: 40px; padding: 6px 14px; /* P2: 38px -> the 40px floor */
  border-radius: 999px; border: 1px solid var(--edge-soft); background: color-mix(in srgb, var(--pl-tile-face) 82%, transparent);
  color: var(--pl-tile-ink); cursor: pointer; }
.pl-favbtn[aria-pressed="true"] { background: #F6B73C; color: #223140; border-color: #B97E10; }
.pl-filter-banner { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 0 auto 10px; width: min(1060px, 100%); background: #223140; color: #FFF;
  border-radius: 12px; padding: 10px 14px; font-size: 14.5px; }
.pl-filter-banner[hidden] { display: none; }
.pl-stage.pl-filtered .pl-page { outline: 3px solid #F6B73C; outline-offset: -3px; border-radius: 18px; }
.pl-tile-fav { position: absolute; top: 8px; left: 8px; z-index: 3; width: 40px; height: 40px; /* P2 (night loop 2026-10-24): was 34px — under the house 40px control floor, same miss P1 fixed on the Ad dismiss chip; rendered at 34x34 in the Round 2 WebKit probe */
  border-radius: 50%; border: 1px solid var(--edge-soft); background: color-mix(in srgb, var(--pl-tile-face) 88%, transparent);
  color: var(--pl-tile-ink-soft); font-size: 17px; line-height: 1; cursor: pointer; display: grid; place-items: center; }
.pl-tile-fav.is-fav { background: #F6B73C; color: #223140; border-color: #B97E10; }
c29-channel { position: relative; }

/* pagination (W-2): a real Next control + edge previews */
.pl-nextbtn { position: absolute; right: 14px; bottom: calc(96px + var(--safe-b)); z-index: 5;
  font: inherit; font-weight: 800; font-size: 14px; min-height: 44px; padding: 8px 18px; border-radius: 999px;
  border: 1px solid var(--edge-soft); background: var(--pl-tile-ink); color: var(--pl-tile-face); cursor: pointer;
  box-shadow: 0 8px 20px rgba(20,40,60,.22); }
.pl-nextbtn[hidden] { display: none; }
.pl-edge { position: absolute; top: 0; bottom: 0; width: 26px; z-index: 4; }
.pl-edge[hidden] { display: none; }
.pl-edge.prev { left: 0; } .pl-edge.next { right: 0; }
/* §42 (W2): the edge arrow itself — a whisper, not a nag. A small
   chevron lives at the edge only while a further page lies that way
   (the zone is [hidden] otherwise); it nudges a few px on a slow,
   quiet cycle and leans in on hover. Reduced motion = stillness. */
.pl-edge::after { position: absolute; top: 50%; font-size: 22px; font-weight: 800; line-height: 1;
  color: var(--pl-tile-ink); opacity: .45; pointer-events: none; }
.pl-edge.next::after { content: "›"; right: 5px; animation: pl-edge-nudge-next 3.4s ease-in-out infinite; }
.pl-edge.prev::after { content: "‹"; left: 5px; animation: pl-edge-nudge-prev 3.4s ease-in-out infinite; }
.pl-edge:hover::after { opacity: .85; }
@keyframes pl-edge-nudge-next { 0%, 100% { transform: translateY(-50%) translateX(0); } 50% { transform: translateY(-50%) translateX(3px); } }
@keyframes pl-edge-nudge-prev { 0%, 100% { transform: translateY(-50%) translateX(0); } 50% { transform: translateY(-50%) translateX(-3px); } }
html[data-motion="reduced"] .pl-edge::after { animation: none; }
@media (prefers-reduced-motion: reduce) { .pl-edge::after { animation: none; } .pl-nextbtn { transition: none; } }
.pl-nextbtn { transition: transform .18s var(--ease), box-shadow .18s var(--ease); }
.pl-nextbtn:hover { transform: translateX(2px); }
.pl-nextbtn:active { transform: translateX(2px) scale(.97); }
.pl-main.peek-next .pl-pages { margin-left: -22px; }
.pl-main.peek-prev .pl-pages { margin-left: 22px; }
.pl-pages { transition: margin-left .25s var(--ease); }

/* the player (Listen lives in the shell; the audio element is
   app-owned, so leaving the Listen place never stops it) */
.pl-player { position: absolute; left: 50%; transform: translateX(-50%); bottom: calc(86px + var(--safe-b));
  z-index: 8; width: min(1060px, calc(100% - 16px)); display: flex; align-items: center; gap: 10px;
  background: var(--pl-tile-ink); color: var(--pl-tile-face); border-radius: 16px; padding: 10px 12px;
  box-shadow: 0 12px 30px rgba(15,25,40,.35); }
.pl-player[hidden] { display: none; }
.pl-player-btn { flex: none; min-width: 44px; height: 44px; border-radius: 50%; border: 0; cursor: pointer;
  background: rgba(255,255,255,.14); color: inherit; font: inherit; font-weight: 800; font-size: 14px; }
.pl-player-main { flex: 1; min-width: 0; }
.pl-player-title { font-size: 13.5px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 4px; }
.pl-player-seek { width: 100%; accent-color: #F6B73C; }
.pl-player-time { font-size: 12px; font-weight: 700; white-space: nowrap; }

/* in-place surfaces: cards, rows, lists */
.pl-card { border: 1px solid var(--edge-soft); border-radius: 14px; padding: 12px 14px; margin-bottom: 10px; background: color-mix(in srgb, var(--pl-tile-face) 94%, transparent); } /* D4 (night loop 2026-10-24): the old ground was var(--pl-sky-wash, rgba(255,255,255,.4)) — --pl-sky-wash is defined only in the pleasant-tide register, so on the Principal stage the 40% white fallback always applied: PIXEL-SAMPLED in the D4 rig (dark) it composites over the plum panel to (129,121,135), and every card text pair D3 computed against tile-face actually rendered at meta/sum 2.72:1, title 3.61:1, state 3.17:1, last-words 3.40:1 — all under the 4.5:1 gate, while the same inks on the panel ground pass (stamp 8.97:1). The tile-face tint is opaque in effect in both themes: dark cards now sit in the panel's own family (~9.9:1 for ink-soft), light is unchanged (~7:1+). */
.pl-card-title { font-size: 15px; font-weight: 700; line-height: 1.35; }
.pl-card-sum { font-size: 13.5px; line-height: 1.5; color: var(--pl-ink-soft); margin-top: 4px; }
.pl-card-rec { font-size: 13px; line-height: 1.5; margin-top: 6px; }
.pl-card-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; align-items: center; }
.pl-card-acts input[type="text"] { flex: 1 1 180px; min-height: 44px; font: inherit; font-size: 14px;
  border-radius: 10px; border: 1px solid var(--edge-soft); padding: 8px 10px; background: var(--pl-tile-face); color: var(--pl-tile-ink); }
/* POLISH (W2): one focus language across the shell — every interactive
   element shows the same clear ring in both themes, and text fields
   answer focus with a border + halo (never outline:none into the void). */
.pl-stage :is(.pl-ep, .pl-result, .pl-favbtn, .pl-guide-item, .pdfed-sw, .wv-beachrow .pl-note-btn):focus-visible {
  outline: 3px solid var(--pl-focus, #2B7DE9); outline-offset: 2px; }
.pl-stage :is(input, textarea, select):focus { border-color: var(--pl-focus, #2B7DE9);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pl-focus, #2B7DE9) 28%, transparent); }
/* A15 ROOT CAUSE (W2): the Filed-under row rendered 269px tall at
   phone width — its seg, squeezed beside the row text, stacked its
   options vertically — and that bloat pushed the Desk's first reply
   box below the fold, where no tap could ever focus it. The row now
   stacks on purpose: words on top, the seg full-width beneath, its
   options in one line. Compact at every width, not just small ones. */
.pl-cat-file-row { flex-direction: column; align-items: stretch; gap: 8px; }
.pl-cat-file-row c29-seg { flex: none; width: 100%; }
.pl-cat-file-row c29-seg button { flex: 1 1 auto; }
.pl-place .pl-cat-file-row .pl-row-sub { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pl-note-btn { transition: transform .15s var(--ease), background .15s var(--ease), box-shadow .15s var(--ease); }
.pl-note-btn:hover { box-shadow: 0 4px 14px rgba(20,40,60,.16); }
.pl-note-btn:active { transform: scale(.97); }
.pl-nextbtn:focus-visible, .pdfed-thumb:focus-visible { outline: 3px solid var(--pl-focus, #2B7DE9); outline-offset: 2px; }

/* ==== §44 BRAND PRESENCE (W2) — the house's mark, by doctrine ====
 * The v7 master ONLY (logos/v7-mark.gif is byte-identical to the
 * master, sha256 99d6850d…), rendered as itself in a fixed slot —
 * never cropped, never regraded, nothing overlaid on it. Dark sky
 * wears the night grade (the toggle law: the toggle is the only
 * thing that changes a logo). The gradient disc it replaces was a
 * placeholder, not a mark. */
.pl-lock-mark { width: 84px; height: 84px; background: none; border-radius: 0; overflow: visible; }
.pl-lock-mark img, .pl-lock-mark video { display: block; width: 84px; height: 84px; border-radius: 50%; animation: pl-mark-in .6s ease both; }
.pl-lock-mark .pl-mark-night { display: none; }
[data-theme="dark"] .pl-lock-mark .pl-mark-day { display: none; }
[data-theme="dark"] .pl-lock-mark .pl-mark-night { display: block; }
.pl-stage.pl-dark .pl-lock-mark .pl-mark-day { display: none; }
.pl-stage.pl-dark .pl-lock-mark .pl-mark-night { display: block; }
@keyframes pl-mark-in { from { opacity: 0; } to { opacity: 1; } }
html[data-motion="reduced"] .pl-lock-mark img, html[data-motion="reduced"] .pl-lock-mark video { animation: none; }
.pl-lock-byline { font-size: 11px; font-weight: 800; letter-spacing: .22em; text-transform: uppercase;
  color: var(--pl-tile-ink-soft); margin: -2px 0 10px; }
.pl-shelf-brand { font-size: 11px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase;
  color: var(--pl-ink-soft); opacity: .75; white-space: nowrap; margin-right: 10px; }
/* at phone width the shelf is full — the wordmark stands down there
   rather than crowd the clock (the veil + Settings carry the brand
   on the phone); it rides the shelf where the shelf has room. */
.pl-stage.pl-compact .pl-shelf-brand, .pl-stage.pl-touch .pl-shelf-brand { display: none; }

/* ==== §46 PINNED-HEADER TREATMENT (W2) — converged onto M1's hook ====
 * COLLISION + CONVERGENCE (logged in PROGRESS §46): M1 landed the pin
 * mechanics first — sticky head + the hook class .pl-head-stuck, with
 * an INTERIM stuck surface (sky at 88%) that passing text ghosted
 * through. W2's first cut named a different hook (pl-head-pinned,
 * WITHDRAWN) and a base bar. The converged design is M1's shape —
 * at rest the head is bare on the sky; when the room scrolls, the
 * stuck state becomes reserved chrome — with W2's material on
 * M1's class, placed at M1's rule below (search "§46 HEAD PIN"):
 * solid tile-face, hairline border, whisper shadow; M1's geometry
 * (radius/padding/margin, zero-jump) untouched. Folder head: M1's
 * hook does not pin the folder room, so no treatment hangs there.
 * REMOVED (Principal ruling, 2026-10-25): the stuck treatment this
 * note converged is deleted outright — watcher, class, and rules.
 * The header holds its resting form at every scroll offset.
 * No scroll-triggered header morphs. Header state changes are
 * animated or do not happen. The history above stands as the record
 * of how the morph got here; it does not authorize restoring it. */
.pl-ep { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; font: inherit; cursor: pointer;
  border: 1px solid var(--edge-soft); background: color-mix(in srgb, var(--pl-tile-face) 94%, transparent); /* P5 (night loop 2026-10-24): re-grounded on the tile face, D4's .pl-card pattern — the wash ground passed but held the shell's thinnest pair (ep meta 4.88–4.90:1 light, sampled in three rounds); sampled after (both engines): title 13.08 dark / 11.67 light, meta 8.56 dark / 5.26 light (was 7.72 / 4.90). The light meta is ink-bound (--pl-tile-ink-soft on near-white), so this buys margin, not parity with card sums. The wash token stays for the chip/stat/wire class, whose pairs carry real margin on it. */ border-radius: 12px;
  padding: 10px 12px; margin-bottom: 8px; color: var(--pl-tile-ink); }
.pl-ep .t { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; line-height: 1.35; }
.pl-ep .m { font-size: 12px; color: var(--pl-tile-ink-soft); font-weight: 700; white-space: nowrap; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; } /* P2: the meta voice was nowrap with no shrink path — on a 314px panel row it starved the title; it now ellipsizes and the title may wrap anywhere */
.pl-ep .t { overflow-wrap: anywhere; }
.pl-ep.is-playing { outline: 2px solid #F6B73C; }
.pl-ov-row { display: flex; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--edge-soft); font-size: 14px; }
.pl-ov-row:last-child { border-bottom: 0; }
.pl-ov-row .n { flex: 0 0 128px; font-weight: 700; }
.pl-ov-row .s { flex: 1; color: var(--pl-ink-soft); line-height: 1.45; }
.pl-code { font-family: ui-monospace, Menlo, monospace; font-size: 12.5px; line-height: 1.55; white-space: pre-wrap;
  background: #223140; color: #EAF4EC; border-radius: 12px; padding: 12px; overflow-x: auto; }
.pl-lesson p { font-size: 14.5px; line-height: 1.6; margin: 0 0 10px; }
.pl-run-out { font-family: ui-monospace, Menlo, monospace; font-size: 12.5px; white-space: pre-wrap;
  background: var(--pl-tile-face); border: 1px solid var(--edge-soft); border-radius: 10px; padding: 10px; margin-top: 8px; min-height: 20px; }
.pl-swatch { display: inline-block; width: 44px; height: 44px; border-radius: 10px; border: 1px solid var(--edge-soft); vertical-align: middle; margin-right: 8px; }
.pl-fig { display: flex; gap: 12px; flex-wrap: wrap; }
.pl-fig figure { margin: 0; width: 200px; border: 1px solid var(--edge-soft); border-radius: 12px; padding: 8px; background: var(--pl-tile-face); }
.pl-fig figcaption { font-size: 12.5px; font-weight: 600; color: var(--pl-ink-soft); margin-top: 6px; line-height: 1.4; }
.pl-fig img { width: 100%; height: auto; display: block; border-radius: 8px; }
.pl-bigbtn { font: inherit; font-weight: 800; font-size: 17px; min-height: 64px; padding: 14px 26px; border-radius: 18px;
  border: 0; background: #AF3718; color: #FFF; cursor: pointer; box-shadow: 0 10px 24px rgba(175,55,24,.35); } /* D3 (night loop 2026-10-24): closes the pair D2 flagged — white 17px/800 on #F46036 was 3.19:1 (17px bold is not WCAG-large text); #C7431F is the chips' proven coral step, 4.94:1, and the shadow already carried its rgb. D6 (night loop 2026-10-25): the coral step moved with the chips to #AF3718 (pure 6.21:1) — see .pl-fb-chip.is-owed; the shadow rgb follows it. */
.pl-bigbtn:active { transform: scale(.97); }
.pl-count { font-size: 30px; font-weight: 800; letter-spacing: -.01em; }
.pl-game-zone { position: relative; height: 190px; border-radius: 14px; overflow: hidden; background: linear-gradient(#BEE7FA, #EFF9FF); border: 1px solid var(--edge-soft); }
.pl-gull { position: absolute; font-size: 30px; transition: left 1.1s linear, top 1.1s linear; user-select: none; }
.pl-crack { position: absolute; inset: 0; pointer-events: none; z-index: 4; opacity: 0; }
.pl-tile-cracked .pl-crack { opacity: 1; }
.pl-tile-cracked { animation: pl-shake calc(320ms / var(--speed)) var(--ease); }

/* the quiet register (Pleasant-Tide, §37) lives at the tail of
   this file — tokens, stilling policy, tenant brands — plus the
   shared layout machinery both registers wear. */

/* weather in the world (W-3) */
.pl-rain { position: absolute; inset: 0; z-index: 2; pointer-events: none; overflow: hidden; }
.pl-rain i { position: absolute; top: -12%; width: 2px; height: 11%; border-radius: 2px;
  background: linear-gradient(rgba(90,140,180,0), rgba(90,140,180,.55)); animation: pl-rainfall linear infinite; }
@keyframes pl-rainfall { to { transform: translateY(120vh); } }
html[data-motion="reduced"] .pl-rain { display: none; }
.pl-gullfly { position: absolute; z-index: 2; pointer-events: none; opacity: .85; }
html[data-motion="reduced"] .pl-gullfly { display: none; }

/* embedded-compact posture (P-1..P-3): framed/small viewports get a
   single native-scrolling column with readable floors — captions
   >=15px, targets >=44pt, host chrome zones kept clear */
.pl-stage.pl-compact { padding-top: 0; }
.pl-stage.pl-compact .pl-main { overflow-y: auto; touch-action: pan-y; overscroll-behavior: contain; padding: 64px 10px 120px; } /* D5 scroll contract */
.pl-stage.pl-compact .pl-pages { display: block; transform: none !important; }
.pl-stage.pl-compact .pl-page { display: grid !important; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px; }
.pl-stage.pl-compact .pl-tile-name { font-size: 16px; }
.pl-stage.pl-compact .pl-dots, .pl-stage.pl-compact .pl-nextbtn, .pl-stage.pl-compact .pl-edge { display: none; }
.pl-stage.pl-compact .pl-favbtn, .pl-stage.pl-compact .pl-tile-fav { min-height: 44px; }
.pl-escape { position: absolute; top: calc(10px + var(--safe-t)); right: 10px; z-index: 9;
  font: inherit; font-size: 13px; font-weight: 800; min-height: 44px; padding: 8px 14px; border-radius: 999px;
  border: 1px solid var(--edge-soft); background: var(--pl-tile-ink); color: var(--pl-tile-face); cursor: pointer; }

/* ==== THE TOUR (§30) — Tink: a flying guide, a dotted flight path,
   a taste-token at the end. Sprite + trail are transform/opacity
   only; the trail is the first shed (perf light / tide / calm). */
.pl-tour { position: absolute; inset: 0; z-index: 30; display: flex; align-items: flex-end; justify-content: center; padding: 16px; pointer-events: none; }
.pl-tour-card { pointer-events: auto; width: min(560px, 100%); background: var(--pl-tile-face); color: var(--pl-tile-ink);
  border-radius: 18px; border: 1px solid var(--edge-soft); box-shadow: 0 18px 44px rgba(15,25,40,.3);
  padding: 14px 16px; display: flex; flex-direction: column; animation: pl-tour-in calc(320ms / var(--speed)) var(--ease) both; }
@keyframes pl-tour-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.pl-tour-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 3px; }
.pl-tour-name { font-size: 11px; font-weight: 800; letter-spacing: .09em; color: var(--pl-tile-ink-soft); }
.pl-tour-snd { font: inherit; font-size: 12px; font-weight: 700; min-height: 40px; /* P12 (night loop 2026-10-25): was 30px — the tour's sound toggle rendered 116-118x30 in every leg of the hunt3 rig (both engines); the 40px floor applies to it like every other control */ padding: 4px 11px; border-radius: 999px;
  border: 1px solid var(--edge-soft); background: transparent; color: var(--pl-tile-ink); cursor: pointer; }
.pl-tour-title { font-size: 17px; font-weight: 800; margin-bottom: 4px; }
.pl-tour-text { font-size: 14.5px; line-height: 1.55; }
.pl-tour-path { display: flex; align-items: center; margin-top: 11px; }
.pl-path-dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; border: 2px solid #B97E10; background: transparent; }
.pl-path-dot.flown { background: #F6B73C; }
.pl-path-dot.now { background: #F6B73C; box-shadow: 0 0 0 4px rgba(246,183,60,.30); }
.pl-path-seg { flex: 0 0 15px; border-top: 2px dotted rgba(185,126,16,.45); }
.pl-path-seg.flown { border-top: 2px solid #B97E10; }
.pl-tour-acts { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; align-items: center; }
.pl-tour-hint { font-size: 13.5px; font-weight: 700; color: #B97E10; }
html[data-theme="dark"] .pl-tour-hint { color: #F2C14E; }
.pl-tour-token { flex: 1 1 100%; display: flex; gap: 12px; align-items: center; margin-bottom: 2px; }
.pl-tour-medal { flex: 0 0 56px; width: 56px; height: 56px; border-radius: 50%; border: 1.5px solid #B97E10;
  background: radial-gradient(circle at 35% 30%, rgba(255,247,224,.95), rgba(246,199,92,.38));
  display: grid; place-items: center; box-shadow: 0 6px 16px rgba(185,126,16,.30); }
.pl-tour-medal svg { width: 44px; height: 44px; }
.pl-tour-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.pl-tour-chip { font-size: 12.5px; font-weight: 700; border: 1px solid var(--edge-soft); border-radius: 999px;
  padding: 5px 10px; background: var(--pl-sky-wash); }
.pl-tour-tokenline { font-size: 13px; font-weight: 600; color: var(--pl-tile-ink-soft); padding: 0 2px 10px; }
/* her layer: above the rooms, haunting nothing she shouldn't */
.pl-tink-layer { position: absolute; inset: 0; z-index: 32; pointer-events: none; overflow: hidden; }
.pl-tink { position: absolute; left: 0; top: 0; width: 60px; height: 60px; will-change: transform; }
.pl-tink-in { width: 100%; height: 100%; will-change: transform; }
.pl-tink-in svg { display: block; width: 100%; height: 100%; overflow: visible; }
.pl-tink-glow { position: absolute; inset: -36px; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(246,199,92,.50), rgba(246,199,92,0) 72%); }
html[data-theme="dark"] .pl-tink-glow { background: radial-gradient(closest-side, rgba(246,211,130,.55), rgba(246,211,130,0) 72%); }
.tk-s0 { stop-color: #FFF7E0; } .tk-s1 { stop-color: #F6C453; } .tk-s2 { stop-color: #E79B2E; }
html[data-theme="dark"] .tk-s0 { stop-color: #FFF3D6; } html[data-theme="dark"] .tk-s1 { stop-color: #EFD28A; } html[data-theme="dark"] .tk-s2 { stop-color: #C9A24B; }
.tk-wing { fill: rgba(140,200,235,.55); }
html[data-theme="dark"] .tk-wing { fill: rgba(178,164,232,.50); }
.tk-wl { transform-box: fill-box; transform-origin: 100% 55%; animation: tk-flap-l var(--tk-flap, 1.15s) ease-in-out infinite alternate; }
.tk-wr { transform-box: fill-box; transform-origin: 0% 55%; animation: tk-flap-r var(--tk-flap, 1.15s) ease-in-out infinite alternate; }
@keyframes tk-flap-l { from { transform: rotate(7deg); } to { transform: rotate(-17deg); } }
@keyframes tk-flap-r { from { transform: rotate(-7deg); } to { transform: rotate(17deg); } }
.tk-core { fill: #FFFDF4; opacity: .92; }
.tk-ink { fill: #223140; }
.tk-smile { stroke: #223140; stroke-width: 1.4; fill: none; stroke-linecap: round; }
.tk-crown { fill: #F6B73C; }
.tk-wand line { stroke: #B97E10; stroke-width: 2; stroke-linecap: round; }
.tk-wand path { fill: #F6B73C; stroke: #B97E10; stroke-width: .7; }
html[data-motion="reduced"] .tk-wl, html[data-motion="reduced"] .tk-wr { animation: none; }
html[data-motion="reduced"] .pl-tour-card { animation: none; }
.pl-tink-trail { position: absolute; inset: 0; }
.pl-spark { position: absolute; left: -7px; top: -7px; font-size: 11px; line-height: 1; color: #F2C14E;
  text-shadow: 0 0 6px rgba(242,193,78,.85); pointer-events: none; will-change: transform, opacity; }
.pl-tour-spot { position: absolute; left: 0; top: 0; border: 2px solid #F6B73C; border-radius: 16px; pointer-events: none;
  box-shadow: 0 0 0 4px rgba(246,183,60,.22), 0 0 26px 6px rgba(246,183,60,.32);
  animation: pl-spot-breathe 2.2s ease-in-out infinite; }
@keyframes pl-spot-breathe { 0%, 100% { box-shadow: 0 0 0 3px rgba(246,183,60,.18), 0 0 20px 4px rgba(246,183,60,.26); } 50% { box-shadow: 0 0 0 5px rgba(246,183,60,.26), 0 0 30px 8px rgba(246,183,60,.38); } }
.pl-tour-spot.pl-spot-pulse { animation: pl-spot-once .6s ease-out; }
@keyframes pl-spot-once { 0% { box-shadow: 0 0 0 2px rgba(246,183,60,.3), 0 0 12px 2px rgba(246,183,60,.3); } 40% { box-shadow: 0 0 0 9px rgba(246,183,60,.4), 0 0 40px 14px rgba(246,183,60,.5); } 100% { box-shadow: 0 0 0 4px rgba(246,183,60,.22), 0 0 26px 6px rgba(246,183,60,.32); } }
html[data-motion="reduced"] .pl-tour-spot { animation: none; }
/* the trail (and her halo) are the first pixels the perf shed takes */
.pl-stage.pl-light .pl-tink-trail, .pl-stage.pl-light .pl-tink-glow,
.pl-stage.pl-pleasant-tide .pl-tink-trail { display: none; }
/* ==== /THE TOUR (§30) ==== */

/* performance posture: the light rendering — expensive pixels shed,
   nothing else changes (PERF-3) */
.pl-stage.pl-light .pl-tile-preview svg * { animation: none !important; }
.pl-stage.pl-light .pl-tile { box-shadow: 0 1px 3px rgba(20,40,60,.18); }
.pl-stage.pl-light .pl-pointer { filter: none; }
.pl-stage.pl-light .pl-rain, .pl-stage.pl-light .pl-gullfly { display: none; }
.pl-pages { will-change: transform; }

/* FLEET D — systems & truth rooms: dimmed rule rows + the composer */
.pl-d-off { opacity: .45; }
.pl-d-area { width: 100%; min-height: 44px; font: inherit; line-height: 1.5; color: var(--pl-tile-ink);
  background: var(--pl-tile-face); border: 1px solid var(--edge-soft); border-radius: 12px; padding: 10px 12px; margin: 4px 0 8px; }
/* Steering #16: the alert channel — a breathing glow, never a flash */
@keyframes pl-alert-breathe { 0%, 100% { box-shadow: 0 0 0 0 rgba(217,119,6,0); } 50% { box-shadow: 0 0 26px 4px rgba(217,119,6, calc(var(--pl-alert-strength, .6) * .55)); } }
.pl-alert { animation: pl-alert-breathe 2.8s ease-in-out infinite; }
.pl-light .pl-alert { animation-duration: 4.5s; }
/* Steering #15: held content composes inside the room */
/* ==== THE HOLDER (§27) — presentation modes for held content ====
   The place panel widens to the room while the holder is active
   (canon keeps its 600px column for every other place), the sheet
   head clears the messages strip via --pl-holder-top (measured live
   by the holder render), and the held guest scrolls INSIDE its
   mode. Modes are layout only — the guest node is never rebuilt. */
/* the sheet itself is a .pl-note (canon caps that class at 680px) —
   while the holder is active the sheet takes the room too, or the
   widened panel overflows a 680px sheet and only its middle shows */
#plPlace.pl-holder-active { width: auto; padding-top: calc(18px + var(--safe-t) + var(--pl-holder-top, 0px)); }
#plPlace.pl-holder-active .pl-sheet-head { width: min(1360px, 100%); }
#plPlace.pl-holder-active .pl-panel { width: min(1360px, 100%); display: flex; flex-direction: column;
  height: calc(100dvh - 176px - var(--pl-holder-top, 0px)); min-height: 320px;
  max-height: calc(100dvh - 176px - var(--pl-holder-top, 0px)); transition: width .45s var(--ease); }
#plPlace.pl-holder-active[data-hmode="frame"] .pl-sheet-head,
#plPlace.pl-holder-active[data-hmode="frame"] .pl-panel { width: min(840px, 100%); }
.pl-holder { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.pl-holder-bar { flex: none; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 10px 2px 12px; }
.pl-holder-name { flex: 1 1 280px; font-size: 13.5px; line-height: 1.5; color: var(--pl-ink-soft); font-weight: 600; }
.pl-holder-modes { display: flex; gap: 6px; flex: none; }
.pl-holder-mode { font: inherit; font-size: 13px; font-weight: 700; min-height: 40px; padding: 6px 13px;
  border-radius: 999px; border: 1px solid var(--edge-soft); background: transparent;
  color: var(--pl-tile-ink); cursor: pointer; }
.pl-holder-mode[aria-pressed="true"] { background: var(--pl-tile-ink); color: var(--pl-tile-face); border-color: transparent; }
.pl-holder-mode:disabled { opacity: .42; cursor: default; }
.pl-holder-split { flex: 1 1 auto; min-height: 0; display: flex; gap: 14px; }
.pl-held { flex: 1 1 auto; min-width: 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  touch-action: pan-y; overflow-anchor: none; /* D5 scroll contract */
  border: 1px solid var(--pl-line); border-radius: 18px; padding: 18px; background: var(--pl-card); }
.pl-held img { max-width: 100%; height: auto; }
.pl-held-settle { animation: pl-holder-settle calc(380ms / var(--speed)) var(--ease) both; }
@keyframes pl-holder-settle { from { opacity: .55; transform: scale(.994); } to { opacity: 1; transform: none; } }
html[data-motion="reduced"] .pl-held-settle { animation: none; }
html[data-motion="reduced"] #plPlace.pl-holder-active .pl-panel { transition: none; }
/* CENTERED FRAME: the guest on a designed stage mat, natural measure */
.pl-holder[data-mode="frame"] .pl-held { border-radius: 26px; border-width: 2px;
  padding: clamp(20px, 4vmin, 40px);
  box-shadow: 0 24px 60px rgba(15,25,40,.25), inset 0 2px 0 rgba(255,255,255,.35); }
.pl-holder[data-mode="frame"] .pl-held > * { max-width: 680px; margin-inline: auto; }
/* SIDE BY SIDE: guest + native companion, one room, no tabs */
.pl-holder-pal { display: none; }
.pl-holder[data-mode="split"] .pl-holder-split { display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(280px, 1fr); }
.pl-holder[data-mode="split"] .pl-holder-pal { display: block; overflow-y: auto; overscroll-behavior: contain;
  touch-action: pan-y; /* D5 scroll contract */
  border: 1px solid var(--edge-soft); border-radius: 18px; padding: 16px;
  background: var(--pl-sky-wash); }
.pl-holder-pal-t { font-size: 16px; font-weight: 800; margin: 0 0 8px; }
.pl-holder-pal-p { font-size: 13.5px; line-height: 1.55; color: var(--pl-ink-soft); margin: 0 0 10px; }
@media (max-width: 1179px) {
  /* narrow rooms fall back to a single full panel, whatever the mode says */
  .pl-holder[data-mode="split"] .pl-holder-split { display: flex; }
  .pl-holder[data-mode="split"] .pl-holder-pal { display: none; }
}
/* CONNECT DATA v1: the shell-fed wire, stamped inside the guest */
.pl-held-wire { display: flex; flex-direction: column; gap: 2px; margin-bottom: 14px;
  border: 1.5px dashed var(--pl-tile-ink-soft, #54687B); border-radius: 14px; padding: 10px 14px;
  background: var(--pl-sky-wash); }
.pl-held-wire-tag { font-size: 11px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; color: var(--pl-ink-soft); }
.pl-held-wire-val { font-size: 16.5px; font-weight: 800; color: var(--pl-tile-ink); }
.pl-held-wire-at { font-size: 12.5px; line-height: 1.45; color: var(--pl-ink-soft); }
/* ---- external doors: a page that lives elsewhere is a marked link out ---- */
.pl-ext-door { display: inline-block; font-weight: 700; padding: 10px 16px;
  border: 2px solid var(--pl-tile-ink); border-radius: 999px;
  color: var(--pl-tile-ink); text-decoration: none; }
/* ==== /THE HOLDER (§27) ==== */
/* TV-1: the ten-foot posture */
.pl-tv .pl-tile-name { font-size: 21px; }
.pl-tv .pl-tile-sub { font-size: 15.5px; }
.pl-tv .pl-clock-time { font-size: 30px; }
.pl-tv :focus-visible { outline-width: 3px; outline-offset: 3px; }
.pl-ov-row.pl-d-rule { align-items: flex-start; }
.pl-ov-row.pl-d-rule .s { text-align: left; }
.pl-ov-row.pl-d-rule .pl-note-btn { flex: 0 0 auto; }

/* ---- Fleet B flagships: Desk + Learn live (2026-10-21) ---- */
.pl-card-headrow { display: flex; align-items: flex-start; gap: 8px; }
.pl-card-headrow .pl-card-title { flex: 1; min-width: 0; }
.pl-card-meta { font-size: 12px; font-weight: 700; color: var(--pl-ink-soft); margin-top: 3px; letter-spacing: .01em; }
.pl-card-detail { font-size: 13.5px; line-height: 1.55; color: var(--pl-ink-soft); margin-top: 6px; white-space: pre-wrap; }
.pl-fb-chip { flex: 0 0 auto; font-size: 11.5px; font-weight: 800; padding: 3px 9px; border-radius: 999px; border: 1px solid var(--edge-soft); background: color-mix(in srgb, var(--pl-tile-ink) 10%, var(--pl-tile-face)); color: var(--pl-tile-ink); white-space: nowrap; } /* D3 (night loop 2026-10-24): the old rgba(255,255,255,.55) ground is theme-blind — RENDERED in the D3 rig (dark): cream #F8EDDC text on the blended #A19BA5 = 2.34:1, the washed-out "Waiting" chip. The tile-ink tint adapts with the theme: ~11:1 light, ~9:1 dark (computed). */
/* D2 (night loop 2026-10-24): white on #F46036 computes to 3.19:1 — fails the 4.5:1 gate at 11.5px chip size. #C7431F is the same coral family at 4.94:1. */
.pl-fb-chip.is-owed { background: #AF3718; border-color: #AF3718; color: #fff; } /* D6 (night loop 2026-10-25): one step darker, #C7431F → #AF3718 (pure pair 4.94 → 6.21:1) — D6 pixel-sampled the coral chips at 4.86–4.95 in every engine/theme (element crops 4.89–4.92), the thinnest real pairs left in the room once D5 stepped .is-on to 6.01; the margin is now real under every instrument. Same step lands on .is-urgent and .pl-bigbtn, which share the step. */
.pl-fb-chip.is-on { background: #256E64; border-color: #256E64; color: #fff; } /* D3 (night loop 2026-10-24): white on #3C978A computed 3.51:1 and rendered rgb(60,151,138) in the D3 rig — the same failing class D2 fixed on owed/urgent, one variant over, and Desk-daily (the Desk head's "N with your words in" chip). #2A7C71 is the same teal family at 4.98:1. D5 (night loop 2026-10-24): one step darker to #256E64 (pure pair 6.01:1) — D4 sampled .is-on at 4.55:1, the thinnest pass in the room; the margin is now real under every instrument. */
.pl-state { font-size: 13px; line-height: 1.5; margin-top: 8px; padding: 8px 10px; border-radius: 10px; background: rgba(127,199,232,.16); border: 1px solid var(--edge-soft); }
.pl-state.is-right { background: rgba(60,151,138,.16); }
.pl-series { margin-top: 10px; }
.pl-ep-ic { flex: 0 0 auto; font-weight: 800; color: var(--pl-ink-soft); width: 18px; text-align: center; }
.pl-lesson-h { font-size: 17px; font-weight: 800; line-height: 1.35; }
.pl-card.is-series { border-color: #F2C98A; }

/* ==== THE COUNTER (§21) — Propaganda's square: pickers, proof, tracking room ==== */
.ctr-steps { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 14px; }
.ctr-step { font-size: 12px; font-weight: 700; letter-spacing: .04em; padding: 6px 11px; border-radius: 999px;
  border: 1px solid var(--edge-soft); color: var(--pl-ink-soft); background: transparent; }
.ctr-step.done { color: var(--pl-ink-soft); border-color: transparent; }
.ctr-step.on { background: var(--pl-tile-ink); color: var(--pl-tile-face); border-color: transparent; }
.ctr-fam { padding: 6px 14px 12px; }
.ctr-fam.on { border-color: var(--pl-tile-ink); }
.ctr-fam-head { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; padding: 8px 0;
  background: none; border: 0; font: inherit; text-align: left; cursor: pointer; color: inherit; }
.ctr-fam-glyph { font-size: 26px; line-height: 1; flex: 0 0 auto; }
.ctr-fam-tt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ctr-fam-price { font-size: 13px; font-weight: 700; color: var(--pl-ink-soft); flex: 0 0 auto; }
.ctr-foodring { font-size: 17px; letter-spacing: .35em; text-align: center; padding: 2px 0 8px; opacity: .9; }
.ctr-fam-opts { border-top: 1px dashed var(--edge-soft); padding-top: 10px; margin-top: 2px; }
.ctr-lab { display: block; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--pl-ink-soft); margin: 14px 0 7px; }
.ctr-fam-opts .ctr-lab:first-child, .ctr-form .ctr-lab { margin-top: 4px; }
.ctr-seg { display: flex; flex-wrap: wrap; gap: 7px; }
.ctr-seg-btn { font: inherit; font-size: 13.5px; font-weight: 600; min-height: 42px; padding: 7px 14px;
  border-radius: 999px; border: 1px solid var(--edge-soft); background: transparent; color: inherit; cursor: pointer; }
.ctr-seg-btn.on { background: var(--pl-tile-ink); color: var(--pl-tile-face); border-color: transparent; }
.ctr-stepper { display: inline-flex; align-items: center; gap: 12px; }
.ctr-step-btn { width: 42px; height: 42px; border-radius: 50%; border: 1px solid var(--edge-soft);
  background: transparent; color: inherit; font: inherit; font-size: 19px; font-weight: 700; cursor: pointer; }
.ctr-step-val { font-size: 14.5px; font-weight: 700; min-width: 74px; text-align: center; }
.ctr-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 14.5px; min-height: 46px;
  border-radius: 10px; padding: 9px 12px; border: 1px solid var(--edge-soft);
  background: var(--pl-tile-face); color: inherit; } /* D6 (night loop 2026-10-25): the --pl-card white-fallback class is CLOSED — --pl-card is defined NOWHERE (computed "" on the Principal stage, both engines, D6-verified), so unlike D5's inert sky-wash fallbacks these fallbacks FIRED on every render: .ctr-input's 55% white over the dark panel composites to (160,154,165) and its cream ink element-samples at 2.37:1 in dark (the D4 failure, live). An input takes the house input ground, var(--pl-tile-face) — the Desk words input's ground; the remaining --pl-card consumers (.cnv-well below, .pl-held's bare use) are closed/re-grounded in the same pass. */
.ctr-input::placeholder { color: var(--pl-tile-ink-soft); opacity: 1; } /* P7 (night loop 2026-10-25): the D4 class, second room — .ctr-input is a raw <input>, not a .t-input, so it missed tide.css's themed-placeholder fix and rendered the UA-default grey on its tile-face ground: ELEMENT-CROP sampled in the P7 states rig at 2.94:1 dark / 2.18:1 light (glyph-core; cluster sampler 3.26 / 2.28), WebKit dark the lone pass at 5.77 (its UA grey differs). The tile-ink-soft pair is D4's proven placeholder ground-pairing (Desk words input: ~8.9 dark / ~5.4 light computed); opacity:1 follows the .t-input precedent. */
.pdfed-input::placeholder, .fd4-link::placeholder, .fd4-pad::placeholder { color: var(--pl-tile-ink-soft); opacity: 1; }
.pl-note-ta::placeholder, .pl-d-area::placeholder, .pl-gram-in::placeholder, .ss-namein::placeholder, .ct-input::placeholder, .ct-qty::placeholder, .pl-climb-input::placeholder, .pl-chat-in::placeholder, .st4-in::placeholder, .plmac-tok::placeholder, .inv-linkrow input::placeholder { color: var(--pl-tile-ink-soft); opacity: 1; } /* D8 (night loop 2026-10-25): the placeholder census remainder P7 banked for Round 8 — every class here is a raw input/textarea on the tile-face ground with NO themed ::placeholder rule, so it rendered the UA default: Chromium rgb(117,117,117) = 3.28:1 pure pair on the dark tile face (cluster-sampled 3.22-3.26 in the D8 rig) and WebKit rgb(171,171,171) = 2.27:1 on the light tile face (cluster 2.26-2.31) — each engine fails the 4.5 gate in the opposite theme, so the family failed in every theme on one engine or the other. Real-room proof: .pl-d-area in Feedback + Rules (3.23-3.24 Chromium dark), .ct-input/.ct-qty in Shopping List, .pl-chat-in in The Lads, .plmac-tok in Macros; the rest synthetic-audited in the live Desk panel (D6 technique), incl. .inv-linkrow input whose ground is the sky-wash (tile-ink-soft pure pairs on its sampled composite: 7.76 dark / 4.93 light). The tile-ink-soft pairing is D4's proven placeholder ground-pairing (8.53 dark / 5.28 light pure). */
.pl-card-acts input::placeholder { color: var(--pl-tile-ink-soft); opacity: 1; } /* D8: bare inputs in action rows — the Widgets stock/watch fields and the workout log field are classless type=text inputs grounded by the .pl-card-acts input[type=text] rule but with the same UA placeholder (real-room sampled in Widgets at 3.25-3.26 Chromium dark / 2.11-2.27 WebKit light); the Converter temperature field (type=number, white UA field grounded in the next rule) shares this placeholder fix. */
.pl-card-acts input[type="number"], .pl-card-acts select { border-radius: 10px; border: 1px solid var(--edge-soft); background: var(--pl-tile-face); color: var(--pl-tile-ink); } /* D8: the Converter's amount/temperature inputs and unit selects are bare elements with inline size styles only — they rendered the white UA field in BOTH themes (synthetic + real-room crops: field rgb(255,255,255) inside the dark room, an off-token foreign surface of the class P1 killed in Learn) while their type=text siblings were already tile-grounded by the .pl-card-acts rule above. Ground-only declarations: no flex/padding change, inline sizes untouched. */
.pl-field-in { background: var(--pl-tile-face); color: var(--pl-tile-ink); border: 1px solid var(--edge-soft); }
.pl-field-in::placeholder { color: var(--pl-tile-ink-soft); opacity: 1; } /* D8: shared field ground for bare inputs created outside any grounded row — adopted at creation by the Toast Lab composer input (app.js), which sat directly in the place body on the white UA field (real-room crop: bg 255,255,255 dark; WebKit light placeholder 2.03-2.30 on white). */
 /* P7 (night loop 2026-10-25): the same class, found by the P7 placeholder audit in the states the sweep never samples — .pdfed-input (PDF Editor passkey, resting state) ELEMENT-CROP sampled 3.25:1 dark and .fd4-pad (Scribble pad) 2.97:1 dark, glyph-core, Chromium (light: UA grey on near-white, marginal). All three classes share the tile-face ground + tile-ink construction of .ctr-input above; .fd4-link (Transfer pickup) is included on that family evidence — its own render needs a live pass state the rig cannot reach, and its placeholder was the same UA grey by the same absence. */
.ctr-form { display: grid; gap: 4px 14px; grid-template-columns: 1fr; margin-bottom: 6px; }
@media (min-width: 640px) { .ctr-form { grid-template-columns: 1fr 1fr; } }
.ctr-err { color: #B3401E; font-size: 13.5px; line-height: 1.5; min-height: 20px; margin: 8px 0 0; }
.pl-stage.pl-dark .ctr-err, [data-theme="dark"] .ctr-err { color: #FF9B7A; }
.ctr-staged { border: 1.5px dashed #B3401E; color: #B3401E; border-radius: 12px; padding: 10px 13px;
  font-size: 13.5px; font-weight: 700; line-height: 1.5; margin-bottom: 12px; }
.pl-stage.pl-dark .ctr-staged, [data-theme="dark"] .ctr-staged { border-color: #FF9B7A; color: #FF9B7A; }
.ctr-bill-row { display: flex; justify-content: space-between; gap: 16px; font-size: 13.5px; line-height: 1.5; padding: 5px 0; }
.ctr-bill-n { font-weight: 700; white-space: nowrap; }
.ctr-bill-total { border-top: 1px solid var(--edge-soft); margin-top: 6px; padding-top: 9px; font-size: 15px; }
.ctr-proof-frame { width: 100%; height: 430px; border: 1px solid var(--edge-soft); border-radius: 10px; margin-top: 10px; background: #FFF; }
@media (max-width: 700px) { .ctr-proof-frame { height: 380px; } }
.ctr-journey { display: flex; flex-direction: column; gap: 4px; margin: 6px 0 4px; }
.ctr-state { display: flex; gap: 11px; align-items: flex-start; padding: 9px 12px; border-radius: 12px;
  border: 1px solid transparent; opacity: .52; }
.ctr-state.done { opacity: .78; }
.ctr-state.now { opacity: 1; border-color: var(--edge-soft); background: var(--pl-sky-wash); }
.ctr-state-dot { font-size: 13px; line-height: 1.5; flex: 0 0 auto; width: 16px; text-align: center; }
.ctr-state.now .ctr-state-dot { color: #F46036; }
.ctr-state-tt { display: flex; flex-direction: column; }
.ctr-state-t { font-size: 14.5px; font-weight: 600; line-height: 1.45; }
.ctr-state-s { font-size: 12px; color: var(--pl-ink-soft); margin-top: 1px; }
.ctr-stamp { font-size: 12.5px; color: var(--pl-ink-soft); margin: 6px 2px 12px; }
.ctr-url { font-size: 13.5px; font-weight: 700; word-break: break-all; margin-top: 5px; }
/* ==== /THE COUNTER ==== */
/* ==== CONVERTER (§26) — drop well, targets, honest progress, results ==== */
.cnv-well { border: 2px dashed var(--edge-soft); border-radius: 16px; padding: 26px 18px; text-align: center;
  cursor: pointer; margin: 4px 0 12px; background: color-mix(in srgb, var(--pl-tile-face) 94%, transparent); } /* D6: re-grounded on the tile face (the D4 .pl-card pattern) — the 35% white fallback fired every render (--pl-card undefined) and element-sampled in dark at title 4.21:1 / sub 3.16:1, both under the gate; see .ctr-input's D6 note. */
.cnv-well.over { border-color: var(--pl-tile-ink); background: var(--pl-tile-face); } /* D6: full tile face on drag-over (was the 60% white fallback). */
.cnv-well:focus-visible { outline: 2.5px solid var(--pl-tile-ink); outline-offset: 2px; }
.cnv-well-t { font-size: 16.5px; font-weight: 700; }
.cnv-well-s { font-size: 12.5px; color: var(--pl-ink-soft); margin-top: 5px; line-height: 1.5; }
.cnv-filecard { border-color: var(--pl-tile-ink); }
.cnv-seg { display: flex; flex-wrap: wrap; gap: 7px; margin: 2px 0 4px; }
.cnv-seg-btn { font: inherit; font-size: 13.5px; font-weight: 600; min-height: 42px; padding: 7px 14px;
  border-radius: 999px; border: 1px solid var(--edge-soft); background: transparent; color: inherit; cursor: pointer; }
.cnv-seg-btn.on { background: var(--pl-tile-ink); color: var(--pl-tile-face); border-color: transparent; }
.cnv-opts { margin: 6px 0 2px; }
.cnv-lab { display: block; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--pl-ink-soft); margin: 12px 0 7px; }
.cnv-range { width: 100%; max-width: 320px; accent-color: var(--pl-tile-ink); min-height: 32px; }
.cnv-barwrap { height: 8px; border-radius: 99px; background: var(--edge-soft); overflow: hidden; margin: 12px 0 2px; }
.cnv-bar { display: block; height: 100%; width: 0%; border-radius: 99px; background: var(--pl-tile-ink); transition: width .25s ease; }
.cnv-barwrap.indet .cnv-bar { width: 38%; transition: none; animation: cnv-slide 1.15s ease-in-out infinite alternate; }
@keyframes cnv-slide { from { margin-left: 0; } to { margin-left: 62%; } }
.cnv-status { font-size: 13.5px; line-height: 1.55; color: var(--pl-ink-soft); min-height: 21px; margin: 8px 2px; }
.cnv-results { display: grid; gap: 12px; }
.cnv-result { padding-top: 12px; }
.cnv-prev { width: 100%; max-height: 300px; object-fit: contain; border-radius: 10px; background: rgba(127,127,127,.12); margin-bottom: 8px; }
.cnv-audio { width: 100%; margin-bottom: 8px; }
.cnv-pdfglyph { display: grid; place-items: center; height: 92px; border-radius: 10px; margin-bottom: 8px;
  background: var(--pl-tile-ink); color: var(--pl-tile-face); font-size: 24px; font-weight: 800; letter-spacing: .14em; }
.cnv-note { font-size: 13px; line-height: 1.5; color: #B3401E; min-height: 0; margin: 6px 0 0; }
.pl-stage.pl-dark .cnv-note, [data-theme="dark"] .cnv-note { color: #FF9B7A; }
.cnv-note:empty { display: none; }
/* ==== /CONVERTER ==== */

/* ==== THE NOTEBOOK (§25) — a room to write in ================================
   Paper-warm in both themes; the writing surface carries its own ink so the
   contrast is the paper's promise, sampled by the rig, not the theme's. */
.pl-nb2-wrap{width:min(720px,100%);margin:0 auto}
.pl-nb2-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:2px 0 10px}
.pl-nb2-count{font-size:13px;font-weight:700;color:var(--pl-ink-soft)}
.pl-nb2-chips{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 14px}
.pl-nb2-chips .pl-favbtn{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pl-nb2-ctx{font-size:12.5px;font-weight:700;letter-spacing:.02em;color:var(--pl-ink-soft);margin:2px 2px 10px}
.pl-nb2-paper{background:#FBF5E4;color:#27313C;border:1px solid var(--edge-soft);border-radius:18px;padding:20px 22px 16px;box-shadow:0 10px 28px rgba(20,40,60,.13)}
.pl-stage.pl-dark .pl-nb2-paper,[data-theme="dark"] .pl-nb2-paper{background:#292118;color:#F3EAD6;box-shadow:0 10px 28px rgba(0,0,0,.42)}
.pl-nb2-title{width:100%;box-sizing:border-box;font-family:var(--font-display);font-size:21px;font-weight:800;letter-spacing:-.01em;color:inherit;background:transparent;border:0;border-bottom:1px solid rgba(127,119,96,.45);border-radius:0;padding:2px 0 10px}
.pl-nb2-title::placeholder{color:inherit;opacity:.75} /* D8 (night loop 2026-10-25): .45 measured 2.55:1 light / 3.84:1 dark (cluster, both engines) on the Notebook paper — the one placeholder family WITH a rule that still failed the gate, missed by P7's no-rule census. .75 computes ~5.7 light / ~7.9 dark on the paper pair and stays visibly quieter than typed ink. */
.pl-nb2-title:focus{outline:none;border-bottom-color:currentColor}
.pl-nb2-ta{width:100%;box-sizing:border-box;font:inherit;font-size:17px;line-height:1.7;color:inherit;background:transparent;border:0;border-radius:0;padding:12px 0 4px;min-height:42dvh;resize:vertical}
.pl-nb2-ta::placeholder{color:inherit;opacity:.75} /* D8: same step as .pl-nb2-title above — identical rule, ground and failure (title is the glyph-dense witness; the textarea shares the pair). */
.pl-nb2-ta:focus{outline:none}
/* the paper acknowledges focus; no form-field rectangle on the writing */
.pl-nb2-paper .pl-nb2-ta:focus,.pl-nb2-paper .pl-nb2-ta:focus-visible,.pl-nb2-paper .pl-nb2-title:focus,.pl-nb2-paper .pl-nb2-title:focus-visible{outline:none}
.pl-nb2-paper:focus-within{border-color:#B49B6A;box-shadow:0 14px 34px rgba(20,40,60,.2)}
.pl-stage.pl-dark .pl-nb2-paper:focus-within,[data-theme="dark"] .pl-nb2-paper:focus-within{border-color:#8A6F4D;box-shadow:0 14px 34px rgba(0,0,0,.55)}
.pl-nb2-state{font-size:12.5px;font-weight:700;color:var(--pl-ink-soft);margin:10px 2px 0;min-height:17px}
.pl-nb2-state.is-err{color:#B3401E}
.pl-stage.pl-dark .pl-nb2-state.is-err,[data-theme="dark"] .pl-nb2-state.is-err{color:#FF9B7A}
.pl-nb2-mail{width:100%;box-sizing:border-box;padding:12px 14px;margin-top:10px;border-radius:12px;border:1px solid var(--edge-soft);background:var(--pl-tile-face);color:var(--pl-tile-ink);font:inherit}
.pl-nb2-row{display:block;width:100%;box-sizing:border-box;text-align:left;font:inherit;cursor:pointer;color:var(--pl-tile-ink);background:var(--pl-sky-wash);border:1px solid var(--edge-soft);border-radius:14px;padding:12px 14px;margin-bottom:8px}
.pl-nb2-row:hover{border-color:var(--pl-tile-ink-soft)}
.pl-nb2-row:focus-visible{outline:3px solid var(--pl-tile-ink);outline-offset:2px}
.pl-nb2-row-t{font-size:15px;font-weight:700;line-height:1.35}
.pl-nb2-row-x{font-size:13.5px;line-height:1.5;color:var(--pl-ink-soft);margin-top:3px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.pl-nb2-row-m{display:flex;flex-wrap:wrap;gap:5px 10px;align-items:center;font-size:12px;font-weight:700;color:var(--pl-tile-ink-soft);margin-top:7px}
.pl-nb2-tag{padding:2px 8px;border-radius:999px;border:1px solid var(--edge-soft);background:var(--pl-tile-face);color:var(--pl-tile-ink);font-size:11.5px}
/* ==== /THE NOTEBOOK ==== */
/* ==== DILLO FLOWS (§27) ==== */
.flw-state { font-size: 13px; font-weight: 800; letter-spacing: .02em; margin-top: 6px; }
.flw-src { font-size: 12px; line-height: 1.5; color: var(--pl-ink-soft); margin-top: 6px; }
/* ==== /DILLO FLOWS (§27) ==== */
/* ==== COMET RUN (§33) ==== */
.cmt-wrap { display: block; }
.cmt-stage { position: relative; width: 100%; aspect-ratio: 16 / 10; border-radius: 18px; overflow: hidden; background: #1D1030; box-shadow: inset 0 0 0 1px rgba(255,240,220,.14), 0 10px 30px rgba(24,10,38,.25); touch-action: none; cursor: pointer; }
@media (max-width: 700px) and (orientation: portrait) { .cmt-stage { aspect-ratio: 4 / 3.9; } }
.cmt-stage:focus-visible { outline: 3px solid var(--pl-tile-ink); outline-offset: 2px; }
.cmt-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.cmt-hud { position: absolute; top: 10px; left: 14px; right: 14px; display: flex; justify-content: space-between; align-items: baseline; gap: 12px; color: #FFF6E8; font-weight: 800; font-size: 15px; letter-spacing: .01em; text-shadow: 0 1px 8px rgba(10,4,20,.6); pointer-events: none; }
.cmt-hud-r { color: #F46036; letter-spacing: .18em; font-size: 14px; white-space: nowrap; }
.cmt-big { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; text-align: center; padding: 20px; color: #FFF6E8; pointer-events: none; text-shadow: 0 2px 14px rgba(10,4,20,.75); }
.cmt-big:empty { display: none; }
.cmt-big b { font-size: clamp(26px, 5.2vw, 40px); font-weight: 900; letter-spacing: .01em; }
.cmt-big span { font-size: clamp(13px, 2vw, 15.5px); font-weight: 650; opacity: .92; max-width: 420px; line-height: 1.45; }
.cmt-acts { margin-top: 12px; }
.cmt-meta { margin-top: 10px; }
.cmt-help .pl-card-sum { margin-top: 8px; line-height: 1.55; }
/* while the game claims the pad door, the place chrome's focus ring
   rests — spatial focus lives on the stage, which keeps its own ring */
#plPlace.pl-comet-live .pl-sheet-head .pl-orb:focus-visible,
#plPlace.pl-comet-live .pl-sheet-head c29-orb:focus-visible { outline: none; }
/* the tile's living spark: two stars breathe (never under reduced motion) */
c29-channel[data-square="comet"] .cmt-tw { animation: cmtTw 2.8s ease-in-out infinite; }
@keyframes cmtTw { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
html[data-motion="reduced"] c29-channel[data-square="comet"] .cmt-tw { animation: none; }
/* ==== /COMET RUN (§33) ==== */
/* ==== GUIDE OVERLAY + WORLD PAUSE + PAD RING (§32/§34, P0-7) ==== */
/* the world holds its breath: every ambient CSS animation under the
   home's theatre (sky, tiles' scenes, strip, rain, Tink) freezes.
   Rooms the person is working in (sheets, places, this overlay) are
   NOT in the frozen set — their entrances still land — and neither
   is anything that tells the truth (the clock is text). */
.pl-stage.pl-world-paused c29-sky *,
.pl-stage.pl-world-paused .pl-main *,
.pl-stage.pl-world-paused .pl-shelf *,
.pl-stage.pl-world-paused .pl-topstrip *,
.pl-stage.pl-world-paused .pl-rain *,
.pl-stage.pl-world-paused .pl-gullfly,
.pl-stage.pl-world-paused .pl-tour *,
.pl-stage.pl-world-paused .pl-tink-layer * { animation-play-state: paused !important; }
/* the pause badge: obvious, not loud — a small pill that fades in
   once the freeze has lasted a beat, and is gone on resume. */
.pl-pause-badge { position: absolute; top: calc(12px + var(--safe-t)); right: 14px; z-index: 43;
  display: flex; align-items: center; gap: 7px; padding: 6px 12px; border-radius: 999px;
  background: var(--pl-tile-face); color: var(--pl-tile-ink); border: 1px solid var(--edge-soft);
  font-size: 12.5px; font-weight: 800; letter-spacing: .04em; opacity: 0; pointer-events: none;
  transition: opacity .45s ease; box-shadow: 0 6px 18px rgba(24, 42, 58, .18); }
.pl-pause-badge[hidden] { display: none; }
.pl-pause-badge.is-on { opacity: .85; }
.pl-pause-badge span { font-size: 10px; letter-spacing: .18em; }
/* the pad's own ring (P0-7): drawn by the shell, never by modality
   heuristics — same dress as the house focus ring, unconditional. */
.pl-pad-ring { outline: none !important; box-shadow: var(--focus) !important; }
/* the Guide overlay: a console quick menu in the shell's motion
   language — scrim, a card that rises and settles, settings first. */
.pl-guide { position: absolute; inset: 0; z-index: 44; display: flex; align-items: center; justify-content: center; padding: 18px; }
.pl-guide[hidden] { display: none; }
.pl-guide-scrim { position: absolute; inset: 0; background: rgba(18, 30, 42, .40); backdrop-filter: blur(3px); opacity: 0; }
.pl-guide.is-on .pl-guide-scrim { animation: pl-guide-fade calc(240ms / var(--speed)) var(--ease) both; }
.pl-guide-card { position: relative; width: min(430px, 100%); max-height: calc(100% - 24px); overflow: auto;
  touch-action: pan-y; overscroll-behavior: contain; /* D5 scroll contract — the quick menu had neither */
  background: var(--pl-tile-face); color: var(--pl-tile-ink); border: 1px solid var(--edge-soft);
  border-radius: 22px; padding: 18px 18px 14px; box-shadow: 0 24px 60px rgba(16, 30, 44, .35); opacity: 0; }
.pl-guide.is-on .pl-guide-card { animation: pl-guide-in calc(320ms / var(--speed)) cubic-bezier(.21,1.24,.36,1) both; }
@keyframes pl-guide-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes pl-guide-in { from { opacity: 0; transform: translateY(14px) scale(.962); } 62% { opacity: 1; transform: translateY(-2px) scale(1.004); } to { opacity: 1; transform: none; } }
html[data-motion="reduced"] .pl-guide.is-on .pl-guide-card,
html[data-motion="reduced"] .pl-guide.is-on .pl-guide-scrim { animation: none; opacity: 1; }
.pl-guide-head { margin-bottom: 6px; }
.pl-guide-name { font-size: 19px; font-weight: 800; }
.pl-guide-sub { font-size: 13px; line-height: 1.45; color: var(--pl-tile-ink-soft); margin-top: 2px; }
.pl-guide-sec { font-size: 11px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase;
  color: var(--pl-tile-ink-soft); margin: 14px 2px 7px; }
.pl-guide-list { display: flex; flex-direction: column; gap: 7px; }
.pl-guide-item { font: inherit; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; min-height: 48px; padding: 10px 14px; border-radius: 14px; cursor: pointer;
  background: transparent; color: inherit; border: 1px solid var(--edge-soft); text-align: left; }
.pl-guide-item:hover { border-color: var(--pl-tile-ink-soft); }
.pl-guide-item[aria-disabled="true"] { opacity: .62; }
.pl-guide-item-name { font-size: 15px; font-weight: 700; }
.pl-guide-state { font-size: 12.5px; font-weight: 800; color: var(--pl-tile-ink-soft); white-space: nowrap; }
.pl-guide-hint { font-size: 12.5px; line-height: 1.5; color: var(--pl-tile-ink-soft); margin-top: 14px; }
/* ==== /GUIDE + PAUSE + PAD RING (§32) ==== */
/* ==== FLOWS PITCH (§36) ==== */
.flp-out{font-family:ui-monospace,"SF Mono",Menlo,Consolas,monospace;font-size:12.5px;line-height:1.55;margin-top:8px;padding:9px 11px;border-radius:10px;border:1px solid var(--edge-soft);background:var(--pl-sky-wash);color:var(--pl-tile-ink);overflow-wrap:anywhere}
/* ==== /FLOWS PITCH (§36) ==== */
/* ==== PDF EDITOR (§38) — a tidy room for pages, pictures and words ==== */
/* the sheet itself is a .pl-note (canon caps that class at 680px) —
   while the editor is live the sheet takes the room too, or the
   widened panel overflows a 680px sheet and only its middle shows
   (the Holder lane's lesson, §27) */
#plPlace.pl-pdfed-live { width: auto; }
#plPlace.pl-pdfed-live .pl-panel { width: min(1240px, 100%); }
#plPlace.pl-pdfed-live .pl-sheet-head { width: min(1240px, 100%); }
.pdfed { display: flex; flex-direction: column; gap: 10px; padding: 6px 0 10px; }
.pdfed.drop { outline: 3px dashed rgba(244,96,54,.55); outline-offset: 5px; border-radius: 18px; }
.pdfed-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.pdfed-docline { display: flex; align-items: baseline; gap: 4px; min-width: 0; }
.pdfed-name { font-size: 19px; font-weight: 800; letter-spacing: -.01em; color: var(--pl-tile-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pdfed-meta { font-size: 13.5px; font-weight: 600; color: var(--pl-tile-ink-soft); white-space: nowrap; }
.pdfed-topacts { display: flex; gap: 8px; flex-wrap: wrap; }
.pdfed-topacts .pl-note-btn { min-height: 40px; }
.pdfed-status { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--pl-tile-ink-soft); min-height: 18px; }
.pdfed-work { display: grid; gap: 16px; align-items: start;
  grid-template-columns: 148px minmax(0, 1fr) 268px;
  grid-template-areas: "rail stage side"; }
.pdfed-rail { grid-area: rail; display: flex; flex-direction: column; gap: 10px; max-height: 72dvh; overflow-y: auto; padding: 2px; }
.pdfed-stagewrap { grid-area: stage; display: flex; justify-content: center; overflow: auto; max-height: 72dvh;
  padding: 12px; background: var(--pl-sky-wash); border: 1px solid var(--edge-soft); border-radius: 18px; }
.pdfed-side { grid-area: side; display: flex; flex-direction: column; min-width: 0; }
.pdfed-thumb { font: inherit; display: flex; flex-direction: column; gap: 5px; align-items: stretch;
  background: none; border: 0; padding: 4px; border-radius: 12px; cursor: pointer; color: var(--pl-tile-ink-soft); }
.pdfed-thumb-face { position: relative; display: block; width: 100%; background: #FFF;
  border: 1.5px solid var(--edge-soft); border-radius: 4px; overflow: hidden; box-shadow: 0 1px 4px rgba(20,35,50,.12); }
.pdfed-thumb.on .pdfed-thumb-face { border-color: #F46036; box-shadow: 0 0 0 2px rgba(244,96,54,.35); }
.pdfed-thumb-img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
.pdfed-thumb-word { position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 11px; font-weight: 800; letter-spacing: .08em; color: #8AA0B0; }
.pdfed-thumb-n { position: absolute; right: 4px; bottom: 4px; font-size: 10px; font-weight: 700;
  background: rgba(34,49,64,.85); color: #FFF; padding: 2px 6px; border-radius: 99px; }
.pdfed-thumb-lab { font-size: 12px; font-weight: 700; text-align: center; }
.pdfed-thumb.on .pdfed-thumb-lab { color: var(--pl-tile-ink); }
.pdfed-thumb-add { align-items: center; justify-content: center; min-height: 52px;
  border: 1.5px dashed var(--edge-soft); border-radius: 12px; font-size: 13.5px; font-weight: 700; }
.pdfed-page { position: relative; flex: 0 0 auto; background: #FFF; border-radius: 3px;
  box-shadow: 0 10px 34px rgba(20,35,50,.20), 0 2px 8px rgba(20,35,50,.14); overflow: hidden; }
.pdfed-bg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.pdfed-bg-word { position: absolute; inset: 0; display: grid; place-items: center; color: #8AA0B0; font-size: 13px; font-weight: 700; }
.pdfed-wm { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%) rotate(-32deg);
  font-size: 52px; font-weight: 800; letter-spacing: .06em; color: rgba(90,100,110,.16);
  pointer-events: none; white-space: nowrap; text-transform: uppercase; }
.pdfed-drawlay { position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; }
.pdfed-page.drawing { cursor: crosshair; touch-action: none; }
.pdfed-el { position: absolute; box-sizing: border-box; cursor: grab; touch-action: none;
  border: 1.5px solid transparent; border-radius: 2px; }
.pdfed-el:active { cursor: grabbing; }
.pdfed-el.sel { border-color: #F46036; box-shadow: 0 0 0 2px rgba(244,96,54,.30); }
.pdfed-el-img { display: block; width: 100%; height: 100%; object-fit: fill; pointer-events: none; }
.pdfed-el-text { line-height: 1.3; white-space: pre-wrap; word-break: break-word; pointer-events: none; padding: 1px 2px; }
.pdfed-el-edit { width: 100%; height: 100%; min-height: 44px; box-sizing: border-box; font: inherit;
  line-height: 1.3; border: 0; outline: 2px solid #F46036; background: rgba(255,255,255,.94); resize: none; padding: 1px 2px; }
.pdfed-handle { display: none; position: absolute; right: -8px; bottom: -8px; width: 16px; height: 16px;
  border-radius: 5px; background: #F46036; border: 2px solid #FFF; box-shadow: 0 1px 5px rgba(20,35,50,.35); cursor: nwse-resize; }
.pdfed-el.sel .pdfed-handle { display: block; }
.pdfed-seg { display: flex; flex-wrap: wrap; gap: 4px; background: var(--pl-sky-wash);
  border: 1px solid var(--edge-soft); border-radius: 999px; padding: 4px; }
.pdfed-seg-btn { font: inherit; font-size: 13px; font-weight: 700; padding: 6px 12px; min-height: 40px; min-width: 40px; /* P12: P6 set the height floor; the 1-char labels (pen widths 3/6) still rendered 32px wide (hunt3 census, both engines) — the floor is both dimensions */ /* P6 (night loop 2026-10-25): was 34px — the PDF Editor's own seg buttons sat under the house 40px control floor (all-places sweep, both engines); the c29 .t-seg floor P3 set never reached this room-local seg */
  border-radius: 999px; border: 0; background: none; color: var(--pl-tile-ink-soft); cursor: pointer; }
.pdfed-seg-btn.on { background: var(--pl-tile-ink); color: var(--pl-tile-face); }
.pdfed-lab { font-size: 12px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--pl-tile-ink-soft); margin: 14px 0 6px; }
.pdfed-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 14px; line-height: 1.45;
  color: var(--pl-tile-ink); background: var(--pl-tile-face); border: 1px solid var(--edge-soft);
  border-radius: 12px; padding: 9px 11px; margin-top: 8px; }
.pdfed-words { resize: vertical; }
.pdfed-swatches { display: flex; gap: 7px; flex-wrap: wrap; }
.pdfed-sw { width: 40px; height: 40px; /* P12: was 30x30 — the pen/colour swatches rendered 30x30 in the PDF Editor's Draw state (hunt3 rig, Chromium dark+light) */ border-radius: 10px; border: 1.5px solid var(--edge-soft); cursor: pointer; padding: 0; }
.pdfed-sw.on { box-shadow: 0 0 0 2.5px var(--pl-tile-face), 0 0 0 4.5px #F46036; }
.pdfed-insp-acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.pdfed-insp-acts .pl-note-btn { min-height: 40px; font-size: 13px; padding: 6px 12px; } /* P6: was 38px — under the 40px floor (sweep, both engines) */
.pdfed-danger { color: #B3371F; }
.pdfed-passrow { display: flex; gap: 8px; align-items: stretch; margin-top: 8px; }
.pdfed-passrow .pdfed-input { margin-top: 0; flex: 1; min-width: 0; }
.pdfed-passrow .pl-note-btn { min-height: 40px; flex: 0 0 auto; }
.pdfed-honest { margin: 2px 0 0; font-size: 13px; line-height: 1.55; color: var(--pl-tile-ink-soft); }
@media (max-width: 980px) {
  .pdfed-work { grid-template-columns: minmax(0, 1fr) 244px; grid-template-areas: "stage side" "rail rail"; }
  .pdfed-rail { flex-direction: row; max-height: none; overflow-x: auto; overflow-y: hidden; }
  .pdfed-thumb { flex: 0 0 92px; }
}
@media (max-width: 700px) {
  .pdfed-work { grid-template-columns: minmax(0, 1fr); grid-template-areas: "stage" "rail" "side"; }
  .pdfed-stagewrap { max-height: 58dvh; padding: 8px; }
  .pdfed-thumb { flex-basis: 76px; }
  .pdfed-wm { font-size: 34px; }
}
/* ==== /PDF EDITOR (§38) ==== */

/* ==== PLEASANT-TIDE (§37 + §40) — the quiet register ============
 * A register, not a fork: one stage class + a brand attribute.
 * Canon paints from the --pl-* tokens, so overriding them here
 * re-dresses every component without touching it. Under the
 * tokens: the stilling policy (keyframes off; transitions — the
 * functional feedback — stay), the tenant brand layer, and the
 * shared layout machinery (drawer direction + category heads)
 * that BOTH registers wear. */

/* -- tokens, light (the house theme: 29Court) -- */
.pl-stage.pl-pleasant-tide {
  --pl-accent: #14507E;
  --pl-sky-top: #F7F9FB; --pl-sky-mid: #F2F5F8; --pl-sky-low: #EDF1F5;
  --pl-sky-wash: rgba(20, 50, 80, .04);
  --pl-ink: #0A2540; --pl-ink-soft: #425466;
  --pl-tile-face: #FFFFFF; --pl-tile-rim: #E3E8EE;
  --pl-tile-ink: #0A2540; --pl-tile-ink-soft: #5A6B7F;
  --pl-bar: rgba(255,255,255,.92); --pl-bar-edge: #E3E8EE;
  --pl-orb-face: #FFFFFF; --pl-orb-ink: #14507E;
  --pl-badge: var(--pl-accent); --pl-on-badge: #FFFFFF;
  --pl-focus: var(--pl-accent);
  --pl-glow: rgba(20, 80, 126, 0);
  --pl-tile-shadow: 0 0 0 1px rgba(10,37,64,.05), 0 1px 2px rgba(10,37,64,.06);
}
/* -- tokens, dark -- */
html[data-theme="dark"] .pl-stage.pl-pleasant-tide {
  --pl-accent: #6FA8DC;
  --pl-sky-top: #0D141B; --pl-sky-mid: #0F1820; --pl-sky-low: #111C26;
  --pl-sky-wash: rgba(160, 195, 230, .05);
  --pl-ink: #E6EDF3; --pl-ink-soft: #9FB0C1;
  --pl-tile-face: #131E29; --pl-tile-rim: #26313D;
  --pl-tile-ink: #E6EDF3; --pl-tile-ink-soft: #93A6B8;
  --pl-bar: rgba(13,20,27,.92); --pl-bar-edge: #26313D;
  --pl-orb-face: #16222E; --pl-orb-ink: #9CC3E5;
  --pl-on-badge: #0D141B;
  --pl-tile-shadow: 0 0 0 1px rgba(255,255,255,.05), 0 1px 2px rgba(0,0,0,.4);
}
/* -- tenant brand: Northwind — a clearly fictional demo tenant
 *    (no such client exists); its whole brand is these tokens -- */
.pl-stage.pl-pleasant-tide[data-brand="northwind"] {
  --pl-accent: #9A6A14;
  --pl-sky-top: #FAF7F1; --pl-sky-mid: #F6F0E5; --pl-sky-low: #F1E8D8;
  --pl-sky-wash: rgba(122, 84, 16, .05);
  --pl-tile-rim: #E7DCC4; --pl-bar-edge: #E7DCC4; --pl-orb-ink: #7A5410;
}
html[data-theme="dark"] .pl-stage.pl-pleasant-tide[data-brand="northwind"] {
  --pl-accent: #D9A441;
  --pl-sky-top: #171410; --pl-sky-mid: #1B1712; --pl-sky-low: #201B15;
  --pl-tile-face: #1E1A15; --pl-tile-rim: #3A3226; --pl-bar-edge: #3A3226;
  --pl-orb-face: #241E16; --pl-orb-ink: #E8BC66;
}
/* the sky, stilled: the painted day layer stands down to a wash
 * in light; in dark the dusk gradient (hardcoded in canon) is
 * replaced by the register's flat field */
.pl-stage.pl-pleasant-tide .pl-sky-day { opacity: 1; }
.pl-stage.pl-pleasant-tide .pl-sun, .pl-stage.pl-pleasant-tide .pl-cloud,
.pl-stage.pl-pleasant-tide .pl-stars, .pl-stage.pl-pleasant-tide .pl-moon,
.pl-stage.pl-pleasant-tide .pl-ember { display: none; }
.pl-stage.pl-pleasant-tide .pl-favbtn[aria-pressed="true"] { background: var(--pl-accent); border-color: var(--pl-accent); color: #fff; }
.pl-stage.pl-pleasant-tide .pl-sky-dusk { background: linear-gradient(180deg, #0D141B 0%, #0F1820 52%, #111C26 100%); }
.pl-stage.pl-pleasant-tide[data-brand="northwind"] .pl-sky-dusk { background: linear-gradient(180deg, #171410 0%, #1B1712 52%, #201B15 100%); }

/* -- the stilling policy: keyframe animation off, house-wide.
 *    Transitions stay — they are the functional feedback (a door
 *    opening, a press answering). Weather theatre never renders. */
.pl-stage.pl-pleasant-tide *, .pl-stage.pl-pleasant-tide *::before, .pl-stage.pl-pleasant-tide *::after { animation: none !important; }
.pl-stage.pl-pleasant-tide .pl-rain, .pl-stage.pl-pleasant-tide .pl-gullfly { display: none !important; }

/* -- tiles in a suit: straighter corners, quieter scenes,
 *    documentation type on the label -- */
.pl-stage.pl-pleasant-tide .pl-tile { border-radius: 10px; }
.pl-stage.pl-pleasant-tide .pl-tile-preview > svg { filter: saturate(.45) contrast(.99); }
.pl-stage.pl-pleasant-tide .pl-tile-name { font-family: -apple-system, "SF Pro Text", "Segoe UI", Roboto, sans-serif; font-weight: 700; letter-spacing: 0; }
.pl-stage.pl-pleasant-tide .pl-sheet h2, .pl-stage.pl-pleasant-tide .pl-folder-title { font-family: -apple-system, "SF Pro Text", "Segoe UI", Roboto, sans-serif; letter-spacing: 0; }

/* -- the tenant mark: placement is brand data (bar / shelf /
 *    none). It dresses Pleasant-Tide only; the living register
 *    never wears it. -- */
.pl-brandmark { display: none; align-items: center; gap: 8px; margin-left: auto; padding-left: 10px; }
.pl-stage.pl-pleasant-tide .pl-brandmark:not([hidden]) { display: inline-flex; }
.pl-brandmark-mono { display: grid; place-items: center; min-width: 26px; height: 26px; padding: 0 5px; border-radius: 7px;
  background: var(--pl-accent); color: #FFF; font-size: 12px; font-weight: 800; letter-spacing: .02em; }
.pl-brandmark-name { font-size: 13px; font-weight: 700; color: var(--pl-tile-ink); white-space: nowrap; }
.pl-shelf .pl-brandmark { margin-left: 0; padding-left: 0; }

/* -- category heads (both registers): a filed roster reads like
 *    an index — a hairline, a name, a count -- */
.pl-cat-head { grid-column: 1 / -1; display: flex; align-items: baseline; gap: 10px; align-self: end;
  padding: 0 4px 2px; border-bottom: 1px solid var(--edge-soft); }
.pl-cat-name { font-size: 12.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--pl-tile-ink); }
.pl-cat-count { font-size: 11.5px; font-weight: 600; color: var(--pl-tile-ink-soft); }
.pl-stage.pl-pleasant-tide .pl-cat-name { font-family: -apple-system, "SF Pro Text", "Segoe UI", Roboto, sans-serif; }

/* -- member filing (Categories lane): the "Filed under" row on a
 *    square's own door — stacked, so a five-way seg never squeezes
 *    the label on a phone; in a room it reads as the room's first
 *    row, under a hairline like every section break -- */
.pl-cat-file-row { flex-direction: column; align-items: stretch; gap: 8px; }
.pl-cat-file-row c29-seg { align-self: flex-start; max-width: 100%; }
.pl-place .pl-cat-file-row { padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid var(--edge-soft); }
.pl-stage.pl-pleasant-tide .pl-cat-head { border-bottom: 1px solid var(--edge-soft); }

/* -- the vertical drawer (both registers): pages stack in one
 *    scrolling column; the flick track stands down (transform is
 *    the X engine's, and it stays out of the drawer's way) -- */
.pl-stage.pl-orient-v { height: 100dvh; }
.pl-stage.pl-orient-v .pl-main { justify-content: flex-start; }
.pl-stage.pl-orient-v:not(.pl-compact) .pl-pages-clip { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; scrollbar-width: thin; touch-action: pan-y; overscroll-behavior: contain; } /* D5 scroll contract */
.pl-stage.pl-orient-v .pl-pages { flex-direction: column; transform: none !important; transition: none; }
.pl-stage.pl-orient-v .pl-page { flex: none; width: 100%; align-content: start; }
.pl-stage.pl-orient-v .pl-nextbtn, .pl-stage.pl-orient-v .pl-edge { display: none; }
.pl-stage.pl-orient-v .pl-main.peek-next .pl-pages, .pl-stage.pl-orient-v .pl-main.peek-prev .pl-pages { margin-left: 0; }
/* ==== /PLEASANT-TIDE (§37 + §40) ==== */
/* ==== ACCOUNT & BILLING (§40) — the account drawer's own chrome ====
   Everything var-driven so the drawer wears both registers (and any
   Pleasant-Tide tenant theme) without a second stylesheet. */
.bil-banner { background: var(--pl-sky-wash); }
.bil-live { display: flex; gap: 9px; align-items: flex-start; margin-top: 10px; padding: 10px 12px;
  border-radius: 12px; border: 1px solid var(--edge-soft); font-size: 13.5px; line-height: 1.5; color: var(--pl-tile-ink); }
.bil-live-dot { flex: none; width: 9px; height: 9px; border-radius: 99px; margin-top: 5px; background: #F46036; }
.bil-chip { display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 99px;
  border: 1px solid var(--edge-soft); font-size: 10px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--pl-tile-ink-soft); vertical-align: 2px; white-space: nowrap; }
.bil-meter { padding: 7px 0; }
.bil-meter-top { display: flex; justify-content: space-between; gap: 10px; font-size: 13.5px; margin-bottom: 5px; }
.bil-meter-name { font-weight: 700; }
.bil-meter-num { color: var(--pl-tile-ink-soft); font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }
.bil-meter-track { height: 8px; border-radius: 99px; background: var(--edge-soft); overflow: hidden; }
.bil-meter-fill { height: 100%; border-radius: 99px; background: var(--pl-accent, #3C978A); }
.bil-row { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--edge-soft); }
.bil-row:last-child { border-bottom: none; }
.bil-row-l { min-width: 0; }
.bil-row-date { font-size: 11.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--pl-tile-ink-soft); }
.bil-row-what { font-size: 14px; font-weight: 600; }
.bil-row-r { display: flex; align-items: center; gap: 10px; flex: 0 1 auto; min-width: 0; flex-wrap: wrap; justify-content: flex-end; } /* P6 (night loop 2026-10-25): was flex:none — the amount+state+Receipt cluster could not shrink, blowing the Billing panel to scrollW 385 vs clientW 352 (escapers to x404, both engines, all-places sweep); the cluster now shrinks and wraps right-aligned inside the row */
.bil-amt { font-size: 14.5px; font-weight: 800; font-variant-numeric: tabular-nums; text-align: right; }
.bil-state { font-size: 12px; font-weight: 700; color: var(--pl-tile-ink-soft); text-align: right; }
.bil-state.ok { color: var(--pl-accent, #2F7D6B); }
/* Pleasant-Tide: the same drawer, documentation manners — tighter
   radii, thinner meters, quieter chips. */
.pl-pleasant-tide .bil-live { border-radius: 8px; }
.pl-pleasant-tide .bil-meter-track { height: 6px; border-radius: 4px; }
.pl-pleasant-tide .bil-meter-fill { border-radius: 4px; }
.pl-pleasant-tide .bil-chip { letter-spacing: .05em; }
.pl-pleasant-tide .bil-banner { background: transparent; }
/* ==== /ACCOUNT & BILLING (§40) ==== */

/* ==== FRONT DOOR: THE TOP ROW (§39 FLEET 1) ====
   The system row's treatment (grammar: FRONT-DOOR-ROSTER.md):
   one tray under the four system boxes, one shared dusk-glass
   material, the sigil rivet centered on each box's top edge, one
   shared sheen pulse traveling the row, the re-deal when the
   system re-chooses. User tiles are untouched by every rule here. */
.pl-page.pl-toprow-on { position: relative; }
.pl-page.pl-toprow-on::before { content: ""; position: absolute; z-index: 0; pointer-events: none;
  left: 4px; right: 4px; top: var(--fd-tray-top, 0px); height: var(--fd-tray-h, 100px);
  border-radius: 24px;
  background: linear-gradient(180deg, rgba(255,255,255,.42), rgba(255,255,255,.16));
  border: 1px solid rgba(255,255,255,.5);
  box-shadow: 0 14px 34px rgba(31,58,84,.13), inset 0 1px 0 rgba(255,255,255,.6); }
html[data-theme="dark"] .pl-page.pl-toprow-on::before {
  background: linear-gradient(180deg, rgba(255,214,170,.13), rgba(255,255,255,.05));
  border-color: rgba(255,226,180,.22);
  box-shadow: 0 14px 34px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,226,180,.18); }
.pl-stage.pl-compact .pl-page.pl-toprow-on::before { border-radius: 18px; }
.pl-page.pl-toprow-on > c29-channel { position: relative; z-index: 1; }

@keyframes fd-sheen {
  0% { background-position: 135% 0, 0 0; }
  32% { background-position: -65% 0, 0 0; }
  100% { background-position: -65% 0, 0 0; } }
@keyframes fd-breathe {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,.85), 0 0 0 2px rgba(244,96,54,.32), 0 8px 20px rgba(31,58,84,.10); }
  50% { box-shadow: inset 0 1px 0 rgba(255,255,255,.85), 0 0 0 3.5px rgba(244,96,54,.58), 0 8px 22px rgba(31,58,84,.12); } }
@keyframes fd-redeal {
  0% { transform: perspective(700px) rotateX(42deg) translateY(8px); opacity: .3; }
  100% { transform: perspective(700px) rotateX(0deg) translateY(0); opacity: 1; } }

c29-channel.pl-sys .pl-tile {
  background:
    linear-gradient(115deg, transparent 30%, rgba(255,255,255,.5) 48%, transparent 62%),
    linear-gradient(165deg, rgba(255,255,255,.92), rgba(224,238,246,.82));
  background-size: 260% 100%, 100% 100%;
  background-position: 135% 0, 0 0;
  border: 1px solid rgba(255,255,255,.7);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.85), 0 8px 20px rgba(31,58,84,.10);
  animation: fd-sheen 14s linear infinite; animation-delay: var(--fd-delay, 0s); }
html[data-theme="dark"] c29-channel.pl-sys .pl-tile {
  background:
    linear-gradient(115deg, transparent 30%, rgba(255,226,180,.16) 48%, transparent 62%),
    linear-gradient(165deg, rgba(70,52,84,.92), rgba(46,36,62,.88));
  border-color: rgba(255,226,180,.25);
  box-shadow: inset 0 1px 0 rgba(255,226,180,.22), 0 8px 20px rgba(0,0,0,.30); }
c29-channel.pl-sys .pl-tile::after { content: ""; position: absolute; z-index: 4; pointer-events: none;
  top: 6px; left: 50%; transform: translateX(-50%);
  width: 11px; height: 11px; border-radius: 50%;
  border: 1.6px solid color-mix(in srgb, var(--pl-tile-ink) 55%, transparent);
  background: radial-gradient(circle at 74% 26%, var(--pl-tile-ink) 0 1.9px, transparent 2.6px);
  opacity: .55; }
c29-channel.pl-sys-live .pl-tile { animation: fd-sheen 14s linear infinite, fd-breathe 2.8s ease-in-out infinite;
  animation-delay: var(--fd-delay, 0s), 0s; }
c29-channel.pl-redeal .pl-tile { animation: fd-redeal .55s cubic-bezier(.2,.8,.25,1) both, fd-sheen 14s linear infinite;
  animation-delay: 0s, var(--fd-delay, 0s); }
c29-channel.pl-sys-live.pl-redeal .pl-tile { animation: fd-redeal .55s cubic-bezier(.2,.8,.25,1) both, fd-sheen 14s linear infinite, fd-breathe 2.8s ease-in-out infinite;
  animation-delay: 0s, var(--fd-delay, 0s), 0s; }

/* the shed + the quiet register: the row keeps its tray, material
   and sigil; motion stands down (perf law; §40 register policy) */
.pl-stage.pl-light c29-channel.pl-sys .pl-tile,
.pl-stage.pl-pleasant-tide c29-channel.pl-sys .pl-tile { animation: none; }
.pl-stage.pl-light c29-channel.pl-sys-live .pl-tile,
.pl-stage.pl-pleasant-tide c29-channel.pl-sys-live .pl-tile { animation: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.85), 0 0 0 2px rgba(244,96,54,.5), 0 8px 20px rgba(31,58,84,.10); }
@media (prefers-reduced-motion: reduce) {
  c29-channel.pl-sys .pl-tile, c29-channel.pl-sys-live .pl-tile, c29-channel.pl-redeal .pl-tile { animation: none !important; } }
/* ==== /FRONT DOOR: THE TOP ROW (§39 FLEET 1) ==== */

/* ==== SIMPLE (§39/§41, Fleet 2) ====
 * Simple is a presentation policy, never a data difference: same
 * squares, same counts, plainer dress. The scene art steps aside
 * for a plain initial chip; the sky flattens; the gloss goes.
 * Everything here is scoped to .pl-simple so Full is untouched. */
.pl-simple-bar { display: none; }
.pl-stage.pl-simple .pl-simple-bar { display: flex; align-items: center; gap: 10px;
  width: min(1060px, 100%); margin: 0 auto 10px; padding: 12px 16px;
  border-radius: 12px; border: 1px solid var(--edge-soft);
  background: var(--pl-tile-face); color: var(--pl-tile-ink-soft);
  font: 600 15px/1.2 var(--font-display); cursor: pointer; text-align: left; }
.pl-simple-bar-ico { font-size: 18px; color: var(--pl-tile-ink); }
.pl-stage.pl-simple c29-sky .pl-sky-day { background: linear-gradient(180deg, #EDF1F4, #EDF1F4); }
.pl-stage.pl-simple c29-sky .pl-sky-dusk { background: linear-gradient(180deg, #131A22, #131A22); }
.pl-stage.pl-simple c29-sky .pl-sun, .pl-stage.pl-simple c29-sky .pl-moon,
.pl-stage.pl-simple c29-sky .pl-stars, .pl-stage.pl-simple c29-sky .pl-ember { opacity: 0 !important; }
.pl-stage.pl-simple .pl-gullfly { display: none; }
.pl-stage.pl-simple .pl-tile { border-width: 1px; border-radius: 14px; box-shadow: none; }
.pl-stage.pl-simple .pl-tile::before { display: none; }
.pl-stage.pl-simple .pl-tile:hover { transform: none; }
.pl-stage.pl-simple .pl-tile-preview { display: none; }
.pl-simple-ico { display: none; }
.pl-stage.pl-simple .pl-simple-ico { display: grid; place-items: center; flex: none;
  width: 38px; height: 38px; margin: 46px 0 0 14px; border-radius: 10px;
  background: var(--pl-sky-wash); color: var(--pl-tile-ink);
  font: 800 17px/1 var(--font-display); }
.pl-stage.pl-simple .pl-tile-label { background: transparent; }
.pl-stage.pl-simple .pl-tile-badge { box-shadow: none; }
/* ==== /SIMPLE (§39/§41, Fleet 2) ==== */

/* ==== FRONT DOOR FLEET 4 (§39) — DRAWERS + EASY TOOLS ==== */
/* Drawers (DRAWER-GRAMMAR.md): a quiet rail under the room's head.
   Shape tokens mirror the house's seg buttons (pl-seg-family) but
   the drawer is a tab, not a toggle: selected = filled, resting =
   outlined, and the fill is the register's own accent so both
   registers dress it from the same custom properties. */
.fd4-rail{flex-wrap:wrap;gap:8px;margin:2px 0 4px;padding:2px 2px 6px;overflow-x:auto;-webkit-overflow-scrolling:touch}
.fd4-drawer{flex:0 0 auto;border:1.5px solid var(--pl-line,var(--edge-soft));background:var(--pl-tile-face);color:var(--pl-tile-ink);
  border-radius:999px;padding:8px 16px;min-height:40px;font:inherit;font-size:14.5px;font-weight:700;cursor:pointer; /* P6: fd4-drawer rendered 39px in WebKit (sweep) — at the 40px floor explicitly now */
  transition:background var(--speed) var(--ease),color var(--speed) var(--ease),border-color var(--speed) var(--ease)}
.fd4-drawer:hover{border-color:var(--pl-tile-ink)}
.fd4-drawer.on{background:var(--pl-tile-ink);border-color:var(--pl-tile-ink);color:var(--pl-tile-face)}
.fd4-drawer:focus-visible{outline:3px solid var(--pl-tile-ink);outline-offset:2px}
.fd4-drawerbody{display:flex;flex-direction:column;gap:14px;min-width:0}
.fd4-acts{flex-wrap:wrap;gap:8px}
/* "what happened" rows — a row is a card-shaped button: title on
   the strong line, WHEN + WHOSE on the soft line. */
.fd4-rowwrap{margin:0;flex-direction:column;align-items:stretch;gap:0}
.fd4-rowbtn{flex:1 1 auto;display:flex;flex-direction:column;align-items:flex-start;gap:3px;text-align:left;
  border:1px solid var(--edge-soft);border-radius:14px;background:var(--pl-sky-wash);
  padding:12px 14px;font:inherit;color:var(--pl-tile-ink);cursor:pointer;min-width:0;
  transition:border-color var(--speed) var(--ease)}
.fd4-rowbtn:hover{border-color:var(--pl-tile-ink)}
.fd4-rowbtn:focus-visible{outline:3px solid var(--pl-tile-ink);outline-offset:2px}
.fd4-row-t{font-size:15.5px;font-weight:800;line-height:1.25;overflow-wrap:break-word}
.fd4-row-s{font-size:13px;color:var(--pl-tile-ink-soft);line-height:1.35;overflow-wrap:break-word}
.fd4-row-det{flex:1 1 auto;border:1px solid var(--edge-soft);border-top:0;border-radius:0 0 14px 14px;
  background:var(--pl-tile-face);color:var(--pl-tile-ink-soft);padding:10px 14px;font-size:14px;line-height:1.45}
/* Transfer */
.fd4-drop{display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;cursor:pointer;
  border:2px dashed var(--pl-line,var(--edge-soft));border-radius:14px;padding:22px 16px;margin-top:10px;
  transition:border-color var(--speed) var(--ease),background var(--speed) var(--ease)}
.fd4-drop:hover,.fd4-drop:focus-within{border-color:var(--pl-tile-ink);background:var(--pl-sky-wash)}
.fd4-drop.over{border-color:var(--pl-tile-ink);background:var(--pl-sky-wash)}
.fd4-drop-big{font-size:16.5px;font-weight:800;color:var(--pl-tile-ink);overflow-wrap:anywhere}
.fd4-drop-sub{font-size:13px;color:var(--pl-tile-ink-soft)}
.fd4-file{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.fd4-seg-lab{font-size:12.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--pl-tile-ink-soft);margin:14px 0 6px}
.fd4-seg{display:inline-flex;gap:6px;flex-wrap:wrap}
.fd4-seg-btn{border:1.5px solid var(--pl-line,var(--edge-soft));background:var(--pl-tile-face);color:var(--pl-tile-ink);
  border-radius:999px;padding:7px 14px;min-height:40px;font:inherit;font-size:14px;font-weight:700;cursor:pointer} /* P6: rendered 37px (sweep, both engines) — 40px floor */
.fd4-seg-btn.on{background:var(--pl-tile-ink);border-color:var(--pl-tile-ink);color:var(--pl-tile-face)}
.fd4-seg-btn:focus-visible{outline:3px solid var(--pl-tile-ink);outline-offset:2px}
.fd4-link{display:block;width:100%;box-sizing:border-box;margin-top:10px;padding:10px 12px;
  border:1px solid var(--edge-soft);border-radius:10px;background:var(--pl-tile-face);color:var(--pl-tile-ink);
  font:inherit;font-size:14px}
/* Scribble pad — paper-ish, generous, one job. */
.fd4-pad{display:block;width:100%;box-sizing:border-box;margin-top:10px;padding:14px;
  border:1px solid var(--edge-soft);border-radius:12px;background:var(--pl-tile-face);color:var(--pl-tile-ink);
  font:inherit;font-size:16.5px;line-height:1.55;resize:vertical;min-height:150px}
.fd4-pad:focus-visible{outline:3px solid var(--pl-tile-ink);outline-offset:1px}
@media (prefers-reduced-motion:reduce){.fd4-drawer,.fd4-rowbtn,.fd4-drop{transition:none}}
/* ==== /FRONT DOOR FLEET 4 (§39) ==== */

/* ================= MOBILE RESCUE (P0 round, 2026-10-21) =================
   One slot arbiter for all chrome; pre-auth the veil is the whole
   surface; touch phones get a native-scroll home; the player owns
   a reserved slot and never sits under a room or host chrome. */

/* host-chrome lift: in the embedded-compact posture the browser's
   own chrome overlays the bottom of the webview; the shelf, the
   player and the rooms all ride this one lift together.
   FLUSH-DOCK ruling (2026-10-25, the Principal): the SHELF no longer
   rides the lift — it docks flush, its bottom margin the safe-area
   inset alone, in every posture; the floating card with dead space
   beneath it is dead. --pl-host-lift remains only for the player /
   playing-sheet fallback offsets below; the shelf's slot is the
   measured reserve (§60/§62), which follows the real margin. */
.pl-stage { --pl-host-lift: 0px; }
.pl-stage.pl-compact { --pl-host-lift: 64px; }
.pl-stage.pl-compact .pl-shelf { margin-bottom: var(--safe-b); }
/* FLUSH-DOCK, every posture: the base dress (tide.css) carried a 10px
   float under the docked bar; the ruling kills it in the shell's own
   sheet too, so a bundle whose tide build predates the tide.css fix
   still docks flush. Top and side placements keep their own margins
   (their more specific §61 rules win over this one). */
.pl-stage .pl-shelf { margin-bottom: var(--safe-b); }

/* pre-auth, the veil is the WHOLE surface: no strip, no pill, no
   next button, no player shows through or above it */
.pl-stage.pl-locked .pl-topstrip,
.pl-stage.pl-locked .pl-escape,
.pl-stage.pl-locked .pl-nextbtn,
.pl-stage.pl-locked .pl-player { visibility: hidden; }

/* slot arbiter: while any room is open the top chrome rests — the
   room's own head owns the top slot outright, nothing superimposes */
.pl-stage.pl-place-open .pl-topstrip, .pl-stage.pl-place-open .pl-escape,
.pl-stage.pl-sheet-open .pl-topstrip, .pl-stage.pl-sheet-open .pl-escape,
.pl-stage.pl-note-open .pl-topstrip, .pl-stage.pl-note-open .pl-escape,
.pl-stage.pl-assist-open .pl-topstrip, .pl-stage.pl-assist-open .pl-escape,
.pl-stage.pl-wave-open .pl-topstrip, .pl-stage.pl-wave-open .pl-escape,
.pl-stage.pl-folder-open .pl-topstrip, .pl-stage.pl-folder-open .pl-escape,
.pl-stage.pl-search-open .pl-topstrip, .pl-stage.pl-search-open .pl-escape { display: none; }

/* the escape pill's reserved slot: in flow, directly under the
   strip (the shell inserts it there) — it docks, never floats */
.pl-escape { position: relative; top: auto; right: auto; align-self: flex-end; margin: 8px 10px 0 auto; z-index: 7; }

/* the touch posture: a native-scroll single column. The stage is
   height-constrained so main is a real scroller, the pages stack,
   and the shelf stays inside the visible viewport */
.pl-stage.pl-touch { height: 100dvh; }
.pl-stage.pl-touch .pl-main { overflow-y: auto; overscroll-behavior: contain; /* D5 scroll contract */
  padding: 10px 10px 24px; touch-action: pan-y; justify-content: flex-start;
  /* §60 SHELF RESERVE (2026-10-23): the scroller ends above the
     shelf's reserved slot — app.js measures the real shelf and
     publishes --pl-shelf-reserve, so the last content row can
     always scroll fully clear of the dock (Overlap Gate). */
  scroll-padding-bottom: calc(var(--pl-shelf-reserve, 0px) + 12px); }
.pl-stage.pl-touch .pl-pages { display: block; transform: none !important; }
/* the clip must not clip in the stacked postures: a flexed,
   overflow:hidden clip swallows the stack's height, so no
   ancestor ever sees overflow and nothing can scroll */
.pl-stage.pl-touch .pl-pages-clip, .pl-stage.pl-compact .pl-pages-clip { overflow: visible; flex: none; }
.pl-stage.pl-touch .pl-page { display: grid !important; grid-template-columns: 1fr 1fr; gap: 12px;
  margin-bottom: 12px; padding: 0; align-content: start; }
.pl-stage.pl-touch .pl-dots, .pl-stage.pl-touch .pl-nextbtn, .pl-stage.pl-touch .pl-edge { display: none; }
/* M2 (2026-10-22): while the tour runs, her card docks ABOVE the shelf
   on the touch stage — the same 88px band the folder and the finder
   already reserve. Without this the card (z-30, bottom-anchored) lies
   across the whole shelf, and the search stop's named deed — tap the
   magnifier — is physically impossible: the tap lands on her card.
   Proven in WebKit: card rect covered orbSearch/orbGear exactly. */
.pl-stage.pl-touch .pl-tour { padding-bottom: calc(88px + var(--safe-b)); }
.pl-stage.pl-touch .pl-tile-name { font-size: 16px; }

/* the player: above every room (z 24 over the sheets' 20, under the
   veil's 50), bottom-anchored over the shelf on the same lift, and
   the open room yields it a reserved slot — content is never
   hidden behind the bar (exactly one bar, in a reserved slot) */
.pl-player { z-index: 24; bottom: calc(86px + var(--safe-b) + var(--pl-host-lift, 0px)); }
.pl-stage.pl-playing .pl-sheet { bottom: calc(88px + var(--safe-b) + var(--pl-host-lift, 0px) + 88px); }
.pl-stage.pl-playing .pl-folder { bottom: calc(88px + var(--safe-b) + var(--pl-host-lift, 0px) + 88px); }

/* the persistent Back (steering #20): inert at Home */
#orbBackGlobal { transition: opacity .2s var(--ease); }
#orbBackGlobal.pl-back-inert { opacity: .35; }
/* FLEET-2 (2026-10-25): while a sheet-family surface is open, its
   head orb is the one back (D8 EXIT LAW) — the shelf's back steps
   out of sight (layout kept) so no screen ever shows two backs. */
#orbBackGlobal.pl-back-suppressed { visibility: hidden; }

/* ==== §46 ROOM HEADERS PIN — mechanics (Mobile Fleet M1) ====
   Every room header (back + title) is fixed chrome in its reserved
   slot: the header sticks at its NATURAL resting offset (top = the
   sheet's own top padding, so the pin engages with zero jump), the
   body scrolls beneath it, and the way back is on screen at any
   depth. There is NO second, scrolled state: this rule plus the
   component rule in tide.css are the header's whole dress — its
   resting form is its only form, at every scroll offset. */
.pl-sheet-head { position: sticky; top: calc(18px + var(--safe-t)); z-index: 6; }
/* §46 STUCK TREATMENT — REMOVED (Principal ruling, 2026-10-25, from
   his own phone): "The header does this horrible snapping when you
   scroll. Any transition must be animated but ideally get rid of
   this terrible change bc it just distracts the user." The two
   .pl-head-stuck rules that stood here (the interim sky wash, then
   W2's solid tile-face pill with hairline border + whisper shadow)
   and the app.js scroll watcher that toggled the class are deleted
   outright. No scroll-triggered header morphs. Header state changes
   are animated or do not happen. Do not re-add a scrolled state to
   the sheet head. */

/* ==== M1 — touch posture keeps the safe-area top inset ====
   The touch-posture .pl-main rule earlier in this file sets a flat
   10px top padding and drops var(--safe-t); on a notched phone with
   the messages strip absent, the first row of squares slid under
   the island (the Principal's 17:58 acceptance picture). Restore
   the inset the canon rule carries. */
.pl-stage.pl-touch .pl-main { padding-top: calc(10px + var(--safe-t)); }

/* ==== SUPERSQUARES (§43) — stream, capture, aftermath ==== */
.ss-ta { width: 100%; margin-top: 8px; }
.ss-stream { border-bottom: 1px solid var(--line, rgba(34,49,64,.14)); padding-bottom: 12px; margin-bottom: 4px; }
.ss-item { display: flex; gap: 10px; align-items: flex-start; padding: 8px 0; border-top: 1px dashed var(--line, rgba(34,49,64,.12)); }
.ss-item:first-of-type { border-top: 0; }
.ss-glyph { font-size: 17px; line-height: 1.3; flex: 0 0 auto; }
.ss-item-main { flex: 1 1 auto; min-width: 0; }
.ss-item-meta { font-size: 11px; font-weight: 700; letter-spacing: .02em; opacity: .62; }
.ss-item-text { margin-top: 2px; white-space: pre-wrap; overflow-wrap: anywhere; }
.ss-item-acts { display: flex; gap: 6px; flex: 0 0 auto; }
.ss-thumb { display: block; margin-top: 6px; max-width: 220px; width: 100%; border-radius: 10px; border: 1px solid var(--line, rgba(34,49,64,.16)); }
.ss-namein { display: block; width: 100%; min-height: 40px; margin-top: 8px; padding: 6px 10px; font: inherit; border-radius: 10px; border: 1px solid var(--line, rgba(34,49,64,.22)); background: var(--pl-tile-face, #fff); color: inherit; }
.ss-digest { margin-top: 10px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--line, rgba(34,49,64,.2)); background: var(--pl-tile-face, #fff); white-space: pre-wrap; overflow-wrap: anywhere; font-size: 13.5px; line-height: 1.45; }
.ss-linkbtn { display: inline-flex; align-items: center; text-decoration: none; }
/* ==== /SUPERSQUARES (§43) ==== */

/* ==== SKIN PACKS — theme as data (loader: app.js SKIN block) ====
   Every rule here is inert unless the stage wears [data-skin]:
   no pack, no change — the house look is the default pack and it
   lives in the token sheets, exactly where it always did. */
/* artwork slot: the horizon skyline rides inside the sky, behind
   every square (the sky is z-index 0 and pointer-events none) */
.pl-skin-skyline { position: absolute; left: 0; right: 0; bottom: 0; height: 36%;
  pointer-events: none; }
.pl-skin-skyline svg { display: block; width: 100%; height: 100%; }
/* artwork slot: the veil medallion + the wearing line */
.pl-skin-veilart { display: grid; place-items: center; margin-bottom: 2px; }
.pl-skin-veilart svg { width: 62px; height: 62px; }
.pl-skin-wearing { font-size: 11.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--pl-ink-soft); margin-top: 3px; }
/* type mood: pack fonts reach the display faces through the vars
   the loader sets; the inherit fallback is the house behavior */
.pl-stage[data-skin] .pl-tile-name { font-family: var(--pl-skin-font-display, inherit); }
.pl-stage[data-skin] .pl-sheet h2, .pl-stage[data-skin] .pl-folder-title,
.pl-stage[data-skin] .pl-lock-card h2 { font-family: var(--pl-skin-font-display, inherit); }
.pl-stage[data-skin].pl-skin-fontbody { font-family: var(--pl-skin-font-body); }
/* motion posture "calm": the weather theatre stands down, the
   interface still moves (same bodies the quiet register hides) */
.pl-stage.pl-skin-calm .pl-sun, .pl-stage.pl-skin-calm .pl-cloud,
.pl-stage.pl-skin-calm .pl-stars, .pl-stage.pl-skin-calm .pl-moon,
.pl-stage.pl-skin-calm .pl-ember, .pl-stage.pl-skin-calm .pl-rain,
.pl-stage.pl-skin-calm .pl-gullfly { display: none !important; }
/* motion posture "still": calm, plus every keyframe stilled —
   transitions stay; they are functional feedback, not theatre */
.pl-stage.pl-skin-still .pl-sun, .pl-stage.pl-skin-still .pl-cloud,
.pl-stage.pl-skin-still .pl-stars, .pl-stage.pl-skin-still .pl-moon,
.pl-stage.pl-skin-still .pl-ember, .pl-stage.pl-skin-still .pl-rain,
.pl-stage.pl-skin-still .pl-gullfly { display: none !important; }
.pl-stage.pl-skin-still *, .pl-stage.pl-skin-still *::before,
.pl-stage.pl-skin-still *::after { animation: none !important; }
/* ==== /SKIN PACKS ==== */

/* ==== SQB CSS (Squares Build-Out lane) ==== */
/* SQB-CSS: build-out crews add rules between these markers only. */
/* SQB-A: feedback send-state line + plain-language reason */
.sqba-state { font-weight: 700; color: var(--pl-tile-ink); }
.sqba-reason { overflow-wrap: anywhere; }
/* SQB-D: Muse refresh stamp, custody detail, Tide name chips */
.sqd-stamp { font-weight: 700; color: var(--pl-tile-ink); }
.sqd-custody-detail { overflow-wrap: anywhere; }
.sqd-names { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 10px; }
.sqd-name { font-size: 12.5px; font-weight: 700; padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--edge-soft); background: var(--pl-sky-wash); color: var(--pl-tile-ink); }
.sqd-gaps .sqd-name { border-color: rgba(244, 96, 54, .55); }
/* SQB-CSS crew C: the Logos exhibit room — rail, framed stage, live line.
   The frame holds the art alone; every label lives beside or below it. */
.sqb-logo-rail { display: flex; gap: 10px; flex-wrap: wrap; margin: 6px 0 4px; }
.sqb-logo-cell { display: flex; flex-direction: column; gap: 6px; width: 104px; }
.sqb-logo-pick { font: inherit; display: flex; flex-direction: column; gap: 6px; align-items: stretch;
  padding: 8px; border-radius: 12px; border: 1px solid var(--edge-soft);
  background: var(--pl-tile-face); cursor: pointer; }
.sqb-logo-pick img { width: 100%; height: auto; display: block; border-radius: 8px; }
.sqb-logo-pick-name { font-size: 12.5px; font-weight: 700; color: var(--pl-ink-soft); text-align: center; }
.sqb-logo-pick[aria-pressed="true"] { outline: 2px solid var(--pl-tile-ink); outline-offset: 1px; }
.sqb-logo-open { display: inline-flex; align-items: center; min-height: 40px; font-size: 12.5px; font-weight: 700; color: var(--pl-tile-ink); line-height: 1.4; } /* P6: was a plain inline link rendering a 35px hit height (sweep, both engines) — 40px floor */
.sqb-logo-stage { margin: 0; border: 1px solid var(--edge-soft); border-radius: 14px;
  padding: 14px; background: var(--pl-tile-face); display: grid; place-items: center; }
.sqb-logo-stage img { width: min(340px, 100%); height: auto; display: block; border-radius: 10px; }
.sqb-logo-now { font-size: 14.5px; line-height: 1.55; font-weight: 600; margin: 4px 0 0; }
/* ==== /SQB CSS ==== */

/* ==== INVITES (§45) ==== */
.inv-chip { display: inline-block; margin-top: 10px; font-size: 12.5px; font-weight: 700;
  padding: 5px 10px; border-radius: 999px; border: 1px solid rgba(217, 164, 65, .65);
  background: rgba(217, 164, 65, .14); color: var(--pl-tile-ink); }
.inv-linkrow { margin: 8px 0 4px; }
.inv-linkrow input { width: 100%; box-sizing: border-box; padding: 10px 12px; font-size: 14px;
  border-radius: 10px; border: 1px solid var(--edge-soft);
  background: var(--pl-sky-wash); color: var(--pl-tile-ink); }
.inv-row .pl-card-headrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.inv-state { font-size: 11.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  padding: 4px 9px; border-radius: 999px; border: 1px solid var(--edge-soft); color: var(--pl-tile-ink); }
.inv-state-minted { border-color: rgba(47, 122, 108, .55); }
.inv-state-claimed { border-color: rgba(217, 164, 65, .65); }
.inv-state-bound { background: rgba(47, 122, 108, .16); border-color: rgba(47, 122, 108, .55); }
.inv-state-revoked, .inv-state-expired { opacity: .62; }
/* ==== /INVITES ==== */

/* ==== DESK-IN-PLEASANT (goodnight order, 2026-10-22) ==============
 * The Desk room, phone-first: one glance says what's waiting, what's
 * urgent (★), what's already carrying his words; one thumb rules it.
 * Tokens only — both registers dress it from the same vars. Big,
 * certain targets; the comment field at 16px so iOS never zooms it;
 * the head is part of the first render (counts repaint in place —
 * nothing appears later and shoves the list). */
.pl-desk-head { margin: 2px 0 14px; }
.pl-desk-big { display: flex; align-items: baseline; gap: 10px; }
.pl-desk-num { font-size: 34px; font-weight: 800; line-height: 1; color: var(--pl-tile-ink); }
.pl-desk-bigtext { font-size: 16.5px; font-weight: 700; line-height: 1.3; color: var(--pl-tile-ink); }
.pl-desk-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.pl-desk-stamp { font-size: 12px; font-weight: 700; color: var(--pl-ink-soft); }
.pl-desk-card { padding: 14px; }
/* F3 PERF R1 (2026-10-25, pleasant-performance): off-screen Desk cards
   skip layout + paint; card heights vary, `auto` remembers each card's
   real height after first render (200px pre-render estimate). */
.pl-desk-card { content-visibility: auto; contain-intrinsic-size: auto 200px; }
.pl-desk-card.is-commented { border-color: var(--pl-accent, #3C978A); }
.pl-desk-cardchips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; flex: 1; min-width: 0; }
/* D2 (night loop 2026-10-24): same pair as .is-owed above — 3.19:1 → 4.94:1. */
.pl-fb-chip.is-urgent { background: #AF3718; border-color: #AF3718; color: #fff; } /* D6: coral step #AF3718, with .is-owed — see the note there. */
.pl-desk-star { min-height: 40px; padding: 6px 12px; flex: 0 0 auto; }
.pl-desk-title { font-size: 16.5px; margin-top: 8px; }
.pl-desk-lastwords { font-size: 13.5px; line-height: 1.5; margin-top: 8px; padding: 8px 10px; border-radius: 10px;
  background: rgba(60,151,138,.14); border: 1px solid var(--edge-soft); }
.pl-desk-lastwords-k { font-weight: 700; }
.pl-desk-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.pl-desk-acts .pl-note-btn { flex: 1 1 96px; min-height: 52px; font-size: 15px; }
.pl-desk-filebtn { min-height: 44px; }
.pl-desk-detail { border-top: 1px dashed var(--edge-soft); padding-top: 8px; }
.pl-desk-words { margin-top: 12px; border-top: 1px solid var(--edge-soft); padding-top: 10px; }
.pl-desk-words-k { display: block; font-size: 12px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--pl-ink-soft); margin-bottom: 6px; }
.pl-desk-words-row { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
.pl-desk-words-row input[type="text"] { width: 100%; min-height: 52px; font: inherit; font-size: 16px;
  border-radius: 12px; border: 1px solid var(--edge-soft); padding: 10px 12px; background: var(--pl-tile-face); color: var(--pl-tile-ink); }
.pl-desk-send { min-height: 52px; width: 100%; }
.pl-card-words::placeholder { color: var(--pl-tile-ink-soft); opacity: 1; } /* D4 (night loop 2026-10-24): the Desk words input is a raw <input>, not a .t-input, so it missed tide.css's themed-placeholder fix (Rev 5/7) and rendered the UA default grey — PIXEL-SAMPLED in the D4 rig at ~3.6:1 in dark AND 3.69:1 in light, both under the gate, on the Desk's main interaction. The tile-ink-soft token pair passes in both themes (dark ~8.9:1, light ~5.4:1, computed against the input's tile-face ground); opacity:1 follows the .t-input precedent so engines cannot dim it back. */
.pl-desk-card.is-ruled { opacity: .92; }
.pl-desk-card.is-ruled .pl-desk-words { margin-top: 10px; }
/* ==== /DESK-IN-PLEASANT ==== */

/* ==== FUN ZONE + MENAGERIE (§51) ==== */
.fz-hero{border:1.5px solid rgba(127,127,127,.35);border-radius:16px;padding:16px;margin:2px 0 6px;background:linear-gradient(135deg,rgba(255,210,63,.16),rgba(255,92,57,.10))}
.fz-hero-name{font-size:22px;font-weight:800;letter-spacing:-.01em}
.fz-hero-sub{font-size:13.5px;line-height:1.45;opacity:.85;margin-top:4px}
.fz-grid{display:grid;grid-template-columns:1fr;gap:10px}
@media (min-width:560px){.fz-grid{grid-template-columns:1fr 1fr}}
.fz-card{border:1.5px solid rgba(127,127,127,.3);border-radius:14px;padding:13px 14px}
.fz-name{font-size:16.5px;font-weight:750}
.fz-sub{font-size:13px;line-height:1.42;opacity:.82;margin-top:3px}
.fz-state{display:inline-block;margin-top:8px;font-size:12px;font-weight:750;border-radius:999px;padding:3px 10px;border:1.2px solid rgba(127,127,127,.4)}
.fz-state.ok{color:#2e7d32;border-color:rgba(46,125,50,.55)}
.fz-state.wait{color:#9a6a00;border-color:rgba(154,106,0,.5)}
.fz-state.table{color:#6a5acd;border-color:rgba(106,90,205,.5)}
.fz-best{font-size:12.5px;font-weight:700;opacity:.75;margin-top:6px}
.fz-btnrow{margin-top:10px;display:flex;gap:8px;flex-wrap:wrap}
.mg-hud{display:flex;gap:8px;flex-wrap:wrap;margin:2px 0 10px}
.mg-chip{font-size:13px;font-weight:750;border:1.3px solid rgba(127,127,127,.4);border-radius:999px;padding:4px 12px;font-variant-numeric:tabular-nums}
.mg-streak{color:#d8492b;border-color:rgba(216,73,43,.55)}
.mg-stage{position:relative;border-radius:14px;overflow:hidden;border:2px solid rgba(90,90,90,.45)}
.mg-canvas{display:block;width:100%;height:auto;touch-action:none}
.mg-over{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;background:rgba(24,32,20,.55);padding:16px;text-align:center}
.mg-over[hidden]{display:none}
.mg-over>div{background:#fffaf0;color:#223140;border-radius:12px;padding:4px 12px}
.mg-over .mg-over-title{font-size:19px;font-weight:850;background:none;color:#fff;text-shadow:0 1px 8px rgba(0,0,0,.4);padding:0}
.mg-over .pl-actrow{background:none;padding:0}
/* ==== /FUN ZONE + MENAGERIE (§51) ==== */

/* ==== LADS SOCIAL (§52) — CHAT · AVATARS · BADGES ==== */
.pl-chat { display: flex; flex-direction: column; text-align: left; }
.pl-chat-prof { display: flex; align-items: center; gap: 12px; }
.pl-chat-prof-txt { flex: 1; min-width: 0; }
.pl-chat-av { border-radius: 50%; overflow: hidden; flex: none; display: flex; align-items: center; justify-content: center; color: #fff; }
.pl-chat-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pl-chat-av svg { width: 100%; height: 100%; display: block; }
.pl-chat-av-letter { font-weight: 800; line-height: 1; }
.pl-chat-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 5px; }
.pl-chat-chip { font-size: 12px; font-weight: 700; padding: 3px 9px; border-radius: 999px; border: 1px solid var(--edge-soft); background: var(--pl-tile-face); color: var(--pl-tile-ink); }
.pl-chat-pres { font-size: 13px; line-height: 1.6; color: var(--pl-ink-soft); margin-bottom: 10px; }
.pl-chat-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--edge-soft); margin-right: 5px; vertical-align: 1px; }
.pl-chat-dot.on { background: #3C978A; }
.pl-chat-seen { opacity: .65; font-size: 12px; }
.pl-chat-msgs { display: flex; flex-direction: column; gap: 12px; margin-bottom: 6px; }
.pl-chat-row { display: flex; gap: 9px; align-items: flex-start; }
.pl-chat-main { flex: 1; min-width: 0; }
.pl-chat-head { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.pl-chat-name { font-weight: 800; font-size: 13px; }
.pl-chat-time { font-size: 11px; opacity: .55; }
.pl-chat-bglyphs { display: inline-flex; gap: 3px; }
.pl-chat-bglyph { font-size: 12px; }
.pl-chat-text { font-size: 14.5px; line-height: 1.5; color: var(--pl-tile-ink); overflow-wrap: break-word; }
.pl-chat-ceremony { text-align: center; padding: 9px 12px; border: 1px dashed var(--edge-soft); border-radius: 12px; background: var(--pl-sky-wash); }
.pl-chat-ceremony-line { font-weight: 800; font-size: 13.5px; color: var(--pl-tile-ink); }
.pl-chat-ctime { font-size: 11px; opacity: .55; margin-top: 2px; }
.pl-chat-comp { display: flex; gap: 8px; margin-top: 10px; }
.pl-chat-in { flex: 1; min-width: 0; font: inherit; min-height: 44px; border-radius: 999px; border: 1px solid var(--edge-soft); padding: 0 16px; background: var(--pl-tile-face); color: var(--pl-tile-ink); }
.pl-chat-award-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; align-items: center; }
.pl-chat-sel { font: inherit; min-height: 44px; border-radius: 10px; border: 1px solid var(--edge-soft); background: var(--pl-tile-face); color: var(--pl-tile-ink); padding: 0 10px; }
.pl-chat-tplgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 12px; }
.pl-chat-tpl { font: inherit; display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 8px 4px 7px; border-radius: 16px; border: 1px solid var(--edge-soft); background: var(--pl-tile-face); color: var(--pl-tile-ink); cursor: pointer; }
.pl-chat-tpl-art { width: 52px; height: 52px; border-radius: 50%; overflow: hidden; display: block; }
.pl-chat-tpl-art svg { width: 100%; height: 100%; display: block; }
.pl-chat-tpl-name { font-size: 11px; font-weight: 700; }
/* ==== /LADS SOCIAL (§52) ==== */

/* ==== SHARE + MACROS (§47/§48) ==== */
.plmac-run { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(14px + env(safe-area-inset-bottom)); z-index: 220; width: min(520px, calc(100vw - 28px)); background: var(--pl-tile-face, #fff); color: var(--pl-tile-ink, #223140); border: 1px solid var(--edge-soft, #B9CBD4); border-radius: 18px; box-shadow: 0 18px 44px rgba(24, 44, 62, .28); padding: 12px 14px 10px; }
.plmac-run-head { display: flex; align-items: baseline; gap: 10px; }
.plmac-run-head b { font-size: 14px; }
.plmac-run-keys { margin-left: auto; font-size: 11px; opacity: .65; font-variant-numeric: tabular-nums; }
.plmac-run-x { border: 0; background: none; font-size: 18px; line-height: 1; cursor: pointer; color: inherit; padding: 2px 4px; }
.plmac-run-steps { margin: 8px 0 2px; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 5px; }
.plmac-step { display: flex; gap: 8px; align-items: baseline; font-size: 12.5px; }
.plmac-step-mark { width: 14px; text-align: center; font-weight: 800; }
.plmac-step-ok .plmac-step-mark { color: #2E7D5B; }
.plmac-step-fail .plmac-step-mark { color: #C4451F; }
.plmac-step-note { opacity: .72; overflow-wrap: anywhere; }
.plmac-card { border: 1px solid var(--edge-soft, #B9CBD4); border-radius: 16px; padding: 12px 14px; margin: 0 0 12px; background: var(--pl-tile-face, #fff); }
.plmac-card-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.plmac-keys { font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--edge-soft, #B9CBD4); }
.plmac-builtin { font-size: 11px; font-weight: 700; color: #41708C; }
.plmac-dup { font-size: 11px; font-weight: 700; color: #C4451F; }
.plmac-run-btn, .plmac-save, .plmac-tok-btn, .plmac-share-btn { font: inherit; font-weight: 700; font-size: 13px; padding: 7px 14px; min-height: 40px; border-radius: 999px; /* P6: the group carried no min-height and rendered 35–36px (Share in PDF Editor, sweep) — 40px floor for the whole button family */ border: 1px solid var(--edge-soft, #B9CBD4); background: var(--pl-tile-face, #fff); color: inherit; cursor: pointer; }
.plmac-run-btn { margin-left: auto; }
.plmac-steps { margin: 10px 0 0; padding-left: 20px; display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; }
.plmac-args { opacity: .66; overflow-wrap: anywhere; }
.plmac-h { font-size: 15px; margin: 20px 0 8px; }
.plmac-edit { width: 100%; box-sizing: border-box; font-family: ui-monospace, Menlo, monospace; font-size: 12px; line-height: 1.5; padding: 10px 12px; border-radius: 14px; border: 1px solid var(--edge-soft, #B9CBD4); background: var(--pl-tile-face, #fff); color: inherit; }
.plmac-msg { font-size: 12px; opacity: .75; margin: 6px 0 0; }
.plmac-tokrow { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 6px; }
.plmac-tok { font: inherit; font-size: 13px; padding: 7px 12px; min-height: 40px; border-radius: 10px; border: 1px solid var(--edge-soft, #B9CBD4); min-width: 220px; background: var(--pl-tile-face, #fff); color: inherit; } /* P8 (night loop 2026-10-25): min-height 40px — the token input rendered 220x36 in the Macros room (P8 enum rig, both engines) while its row's buttons carry P6's 40px floor; the input was the one member of the row under the floor. */
.plmac-actions { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; }
.plmac-sharebar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 14px; }
.plmac-share-out { font-size: 12.5px; overflow-wrap: anywhere; }
.plmac-share-link { font-weight: 700; overflow-wrap: anywhere; }
/* ==== /SHARE + MACROS (§47/§48) ==== */

/* ==== §56 BOOT + CUTESY (ct-*) ====
 * The boot screen: the v7 master on the house sky (the same sky
 * gradient tokens the shell itself wears), painted by the HTML
 * alone — it is on screen before a line of app.js runs, and app.js
 * only ever dismisses it. Fixed mark slot (132px reserved — a slow
 * network can never move the page around the mark, doctrine rule 7);
 * the loading line lives in its own slot BELOW the mark, never on
 * the artwork. Day/night pair per the toggle law, mirroring §44. */
/* M2 (2026-10-22): a splash never takes input. Until this line the boot
   layer (z-60, inset 0) sat over the veil (z-50) eating real taps —
   elementFromPoint at the gate's Go button returned .pl-boot, so the
   form never submitted and the veil read as dead — while its dismissal
   waits on animation frames a cold phone may not grant promptly. The
   mark still paints and fades exactly as designed; fingers pass
   through it to the gate from the first paint. */
.pl-boot { pointer-events: none; }
.pl-boot { position: fixed; inset: 0; z-index: 60; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px; padding: 24px; text-align: center;
  background: linear-gradient(180deg, var(--pl-sky-top) 0%, var(--pl-sky-mid) 52%, var(--pl-sky-low) 100%);
  color: var(--pl-tile-ink); opacity: 1; transition: opacity .45s ease; }
.pl-boot.pl-boot-out { opacity: 0; pointer-events: none; }
html[data-motion="reduced"] .pl-boot { transition: none; }
.pl-boot-mark { width: 132px; height: 132px; flex: none; }
.pl-boot-mark img, .pl-boot-mark canvas, .pl-boot-mark video { display: block; width: 132px; height: 132px; border-radius: 50%; }
.pl-boot-mark .pl-mark-night { display: none; }
[data-theme="dark"] .pl-boot-mark .pl-mark-day { display: none; }
[data-theme="dark"] .pl-boot-mark .pl-mark-night { display: block; }
.pl-boot-word { font-size: 30px; font-weight: 800; letter-spacing: -.01em; line-height: 1.1; }
.pl-boot-byline { font-size: 11px; font-weight: 800; letter-spacing: .22em; text-transform: uppercase;
  color: var(--pl-tile-ink-soft); }
.pl-boot-slot { height: 22px; margin-top: 8px; display: flex; align-items: center; gap: 8px; }
.pl-boot-pulse { width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: .45;
  animation: ct-boot-pulse 1.6s ease-in-out infinite; }
@keyframes ct-boot-pulse { 0%, 100% { opacity: .22; } 50% { opacity: .6; } }
html[data-motion="reduced"] .pl-boot-pulse { animation: none; opacity: .45; }
.pl-boot-line { font-size: 13px; font-weight: 600; color: var(--pl-tile-ink-soft); }

/* The cutesy rooms — small, warm, one column of truth. */
.ct-now { display: flex; align-items: baseline; justify-content: center; gap: 12px; margin: 2px 0 2px; } /* F5: centered with the ct column (below) */
.ct-now-temp { font-size: 44px; font-weight: 800; letter-spacing: -.02em; line-height: 1; }
.ct-now-lab { font-size: 17px; font-weight: 700; }
.ct-line { font-size: 14.5px; line-height: 1.5; margin: 3px 0; text-align: center; } /* F5 (2026-10-25): the cutesy rooms are a centered one-column readout — Victor's live Golden Hour renders centered; the staged column had drifted left, which is also what stranded the Refresh row at the left edge. */
.ct-dim { color: var(--pl-tile-ink-soft); }
.ct-drow { display: flex; align-items: center; gap: 10px; padding: 8px 2px;
  border-bottom: 1px solid var(--edge-soft); font-size: 14.5px; }
.ct-drow:last-child { border-bottom: none; }
.ct-drow-day { flex: 0 0 86px; font-weight: 750; }
.ct-drow-lab { flex: 1 1 auto; color: var(--pl-tile-ink-soft); }
.ct-drow-rain { flex: 0 0 auto; font-weight: 650; color: #2B7DE9; }
.ct-drow-hilo { flex: 0 0 auto; font-weight: 750; font-variant-numeric: tabular-nums; }
.ct-stamp { font-size: 12.5px; font-weight: 600; color: var(--pl-tile-ink-soft); margin-top: 10px; line-height: 1.5; text-align: center; } /* F5: centered with the ct column */
.ct-mkt { padding: 10px 2px; border-bottom: 1px solid var(--edge-soft); }
.ct-mkt:last-child { border-bottom: none; }
.ct-mkt-name { font-size: 16px; font-weight: 750; line-height: 1.3; }
.ct-mkt-meta { font-size: 13.5px; color: var(--pl-tile-ink-soft); margin: 2px 0 6px; line-height: 1.45; }
.ct-chip { display: inline-block; font-size: 11.5px; font-weight: 800; letter-spacing: .04em;
  border-radius: 999px; padding: 2px 9px; margin-left: 8px; vertical-align: 2px;
  border: 1.2px solid rgba(46,125,50,.55); color: #2e7d32; }
.ct-law { border: 1.5px solid rgba(127,127,127,.35); border-radius: 14px; padding: 12px 14px;
  font-size: 14px; line-height: 1.55; margin: 2px 0 12px; }
.ct-addrow { display: flex; gap: 8px; margin: 4px 0 10px; }
.ct-input { flex: 1 1 auto; min-width: 0; font: inherit; font-size: 15px; padding: 9px 12px;
  border-radius: 10px; border: 1.5px solid rgba(127,127,127,.4); background: var(--pl-tile-face); color: var(--pl-tile-ink); }
.ct-qty { flex: 0 0 64px; min-width: 0; font: inherit; font-size: 15px; padding: 9px 8px; text-align: center;
  border-radius: 10px; border: 1.5px solid rgba(127,127,127,.4); background: var(--pl-tile-face); color: var(--pl-tile-ink); } /* P8 (night loop 2026-10-25): min-width:0 — without it the qty field's automatic minimum size (a default-size number input's content floor, ~205px rendered) ate the whole add row and crushed the flexible .ct-input to a 26px slit in BOTH engines (rendered + in-page-isolated in the P8 enum rig; the Shopping List room had never been opened by any sweep — it is not in the 38-id list). With the floor released the basis rules: qty 64px, item input 166px at 390. */
.ct-item { display: flex; align-items: center; gap: 10px; padding: 8px 2px; border-bottom: 1px solid var(--edge-soft); }
.ct-item:last-child { border-bottom: none; }
.ct-check { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 8px; cursor: pointer;
  border: 2px solid rgba(127,127,127,.55); background: none; color: #2e7d32; font-size: 15px; font-weight: 900;
  display: grid; place-items: center; padding: 0; }
.ct-item-txt { flex: 1 1 auto; font-size: 15px; line-height: 1.4; }
.ct-item.done .ct-item-txt { text-decoration: line-through; color: var(--pl-tile-ink-soft); }
.ct-item-qty { flex: 0 0 auto; font-size: 12.5px; font-weight: 800; border: 1.2px solid rgba(127,127,127,.4);
  border-radius: 999px; padding: 1px 8px; }
.ct-item-by { flex: 0 0 auto; font-size: 11px; font-weight: 700; color: var(--pl-tile-ink-soft); }
.ct-x { flex: 0 0 auto; border: none; background: none; cursor: pointer; font: inherit; font-size: 16px;
  color: var(--pl-tile-ink-soft); padding: 2px 6px; }
.ct-prep { white-space: pre-wrap; font-size: 14px; line-height: 1.6; border: 1.5px dashed rgba(127,127,127,.45);
  border-radius: 12px; padding: 12px 14px; margin: 8px 0; }
.ct-btnrow { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; justify-content: center; } /* F5: the row centers with its room — it was the one left-aligned element in a centered column (button sat 110px off-center, both engines, both ct rooms) */
/* Golden Hour room — the light, drawn and measured (Fleet 8, 2026-10-25).
   Content only: verdict, live clock line, sun arc, light strip, beats.
   Sheet head, nav and button chrome belong to the other fleets.
   Canonization candidates for Fleet 10: .gh-arc (a day-path dial) and
   .gh-strip (a segmented day strip with a now-tick) are generic shapes —
   any room with a day to draw could wear them. */
.gh-verdict-wrap { margin: 12px 0 4px; background: var(--pl-tile-face); } /* the background is load-bearing, not decoration: bold text under the sticky sheet head loses glyph stems in both rig rasterizers (Fleet 8 band investigation, shots-f8 + FLEET-8 record) unless its wrap paints opaque — the face colour matches the panel, so nothing visible changes. The arc leads the room for the same reason: shapes are immune, so the headline starts below the band */
.gh-verdict { font-size: 24px; font-weight: 800; letter-spacing: -.01em; line-height: 1.15; } /* 24px, never 23: Nunito 800 at exactly 23px loses glyph stems (T, li) in the software rasterizers both rigs use — proven in shots-f8, 23 vs 24 side by side */
.gh-why { font-size: 14.5px; line-height: 1.5; margin: 4px 0 0; color: var(--pl-tile-ink-soft); }
.gh-count { font-size: 16.5px; font-weight: 750; line-height: 1.4; margin: 10px 0 2px; }
.gh-arcbox { margin: 4px -4px 0; }
.gh-arc { display: block; width: 100%; height: auto; }
.gh-arc-base { fill: none; stroke: var(--edge-soft); stroke-width: 2; stroke-dasharray: 3 5; stroke-linecap: round; }
.gh-arc-done { fill: none; stroke: var(--pl-tile-ink-soft); stroke-width: 2.5; stroke-linecap: round; }
.gh-arc-gold { fill: none; stroke: #E39A2D; stroke-width: 5; stroke-linecap: round; }
.gh-arc-sea { stroke: var(--edge-soft); stroke-width: 1.5; }
.gh-sun { fill: #F2A93B; stroke: #B97A1E; stroke-width: 1.5; }
.gh-sun-down { fill: var(--pl-tile-ink-soft); stroke: none; opacity: .45; }
.gh-sun-glow { fill: #F2A93B; opacity: .18; }
.gh-stripwrap { margin: 10px 0 2px; }
.gh-strip { position: relative; height: 10px; border-radius: 5px; overflow: hidden; background: var(--pl-sky-wash); }
.gh-seg { position: absolute; top: 0; bottom: 0; }
.gh-seg-day { background: #7FB2D9; }
.gh-seg-gold { background: #E39A2D; }
.gh-seg-dusk { background: #6E5A9E; }
.gh-tick { position: absolute; top: 0; bottom: 0; width: 3px; margin-left: -1.5px; background: var(--pl-ink); border-radius: 2px; box-shadow: 0 0 0 1.5px var(--pl-tile-face); }
.gh-striplabs { display: flex; justify-content: space-between; font-size: 13px; font-weight: 650; color: var(--pl-tile-ink-soft); margin-top: 5px; }
.gh-row { display: flex; align-items: baseline; gap: 10px; padding: 7px 2px; border-bottom: 1px solid var(--edge-soft); }
.gh-beats .gh-row:last-child { border-bottom: none; }
.gh-row-name { flex: 0 0 96px; font-weight: 750; font-size: 14.5px; }
.gh-row-note { flex: 1 1 auto; color: var(--pl-tile-ink-soft); font-size: 13.5px; }
.gh-row-when { flex: 0 0 auto; font-weight: 750; font-variant-numeric: tabular-nums; font-size: 14.5px; }
/* ==== /§56 BOOT + CUTESY ==== */
/* ==== APP STORE · INSTALL (§59 L4) ==== */
.st4-decl { margin-top: 8px; }
.st4-rec { font-size: 12.5px; opacity: .85; margin-top: 2px; }
.st4-in { display: block; width: 100%; box-sizing: border-box; min-height: 44px; font: inherit; border-radius: 10px; border: 1px solid var(--edge-soft); padding: 8px 10px; margin-bottom: 8px; background: var(--pl-tile-face); color: var(--pl-tile-ink); }
/* ==== /APP STORE · INSTALL (§59 L4) ==== */

/* ==== PERSONA KITS (§59 LANE 6) ====
   The login callout bar: a sibling of the top strip, wearing the
   strip's own grammar — present on home, gone under every stage
   state that covers the chrome, absent entirely when empty. */
.pl-kitbar { position: relative; z-index: 7; width: min(1060px, calc(100% - 20px)); margin: 8px auto 0;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--pl-tile-face); color: var(--pl-tile-ink); border: 1px solid var(--edge-soft);
  border-radius: 14px; padding: 9px 12px; font-size: 13.5px; font-weight: 600;
  box-shadow: 0 8px 24px rgba(20,40,60,.14); }
.pl-kitbar[hidden] { display: none; }
.pl-kitbar .grow { flex: 1; min-width: 180px; }
.pl-kitbar .kit-line { display: block; font-weight: 500; font-size: 12.5px; color: var(--pl-tile-ink-soft); margin-top: 2px; }
.pl-kitbar button { flex: none; }
.pl-stage.pl-locked .pl-kitbar,
.pl-stage.pl-place-open .pl-kitbar,
.pl-stage.pl-sheet-open .pl-kitbar,
.pl-stage.pl-note-open .pl-kitbar,
.pl-stage.pl-assist-open .pl-kitbar { display: none; }
.pl-kitchips { display: flex; gap: 6px; flex-wrap: wrap; width: 100%; }
.pl-kitchip { font-size: 12px; font-weight: 700; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--edge-soft); background: color-mix(in srgb, var(--pl-tile-face) 70%, transparent); color: var(--pl-tile-ink-soft); }
.pl-kitchip.on { color: var(--pl-tile-ink); border-color: #2FA84F; }
/* the kits place: one card per kit, one row per app, grants in words */
.pl-kitapp { border: 1px solid var(--edge-soft); border-radius: 12px; padding: 10px 12px; margin: 8px 0;
  background: color-mix(in srgb, var(--pl-tile-face) 60%, transparent); }
.pl-kitapp-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pl-kitapp-name { font-weight: 800; font-size: 15px; }
.pl-kitapp-state { font-size: 12px; font-weight: 700; color: var(--pl-tile-ink-soft); }
.pl-kitapp-state.on { color: #2FA84F; }
.pl-kitgrant { font-size: 12.5px; line-height: 1.45; color: var(--pl-tile-ink-soft); margin-top: 4px; }
.pl-kitgrant b { color: var(--pl-tile-ink); font-weight: 700; }
/* ==== /PERSONA KITS (§59 LANE 6) ==== */

/* ==== LAD PHONE DOOR (§53) ==== */
.pl-lock-or { text-align: center; font-size: 12px; letter-spacing: .18em; opacity: .55; margin: 16px 0 8px; }
.pl-lock-phone-note { font-size: 13.5px; line-height: 1.45; opacity: .8; margin: 0 0 10px; }
.pl-lock-ladder { margin-top: 14px; border-top: 1px solid rgba(127, 127, 127, .25); padding-top: 12px; }
.pl-lock-ladder-link { display: inline-block; font-size: 14.5px; font-weight: 600; margin: 2px 0 12px; }
.pl-lock-continue { width: 100%; margin-top: 12px; }
/* ==== /LAD PHONE DOOR (§53) ==== */

/* ==== AD OF THE DAY ====
   The daily specimen card, in normal flow between the filter
   banner and the squares clip — plain in-flow content (no
   absolute/fixed positioning), so it can never overlap the
   squares grid, the dots nav, the next button, the edges, or
   the player/listener bar in any state. All colour rides the
   shell's own vars (--pl-tile-face / --pl-tile-ink /
   --pl-tile-ink-soft / --edge-soft), which already flip for
   [data-theme="dark"] and the Pleasant-Tide register — no
   hardcoded colours here. HARD LAW, same as the JS: no text
   ever overlays the photo — the label row is chrome above the
   frame, the caption is a sibling below it.
   Space: while hidden (no ad today / API down) the section is
   display:none and reserves nothing. Once the ad JSON returns,
   the JS unhides it before the photo loads: the section's
   min-height plus the frame's fixed aspect-ratio box reserve
   the card's full space in one step, so there is zero layout
   shift and the image only fades in inside its frame. */
.pl-adotd { flex: none; width: min(1060px, calc(100% - 20px)); margin: 0 auto 10px; min-height: 180px;
  color: var(--pl-tile-ink); }
.pl-adotd[hidden] { display: none; }
.pl-adotd-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 2px 2px 8px; }
.pl-adotd-kicker { font-size: 11px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  color: var(--pl-tile-ink-soft); }
.pl-adotd-day { font-size: 12.5px; font-weight: 600; color: var(--pl-tile-ink-soft); white-space: nowrap; }
/* the dismissal cluster: day + close, riding the chrome row at
   the right — the button is a plain round chip in the shell's
   own vars, never a badge on the artwork */
.pl-adotd-right { display: inline-flex; align-items: center; gap: 10px; }
.pl-adotd-close { appearance: none; -webkit-appearance: none; margin: 0; padding: 0;
  width: 40px; height: 40px; border-radius: 999px; display: inline-grid; place-items: center;
  border: 1px solid var(--edge-soft); cursor: pointer;
  background: color-mix(in srgb, var(--pl-tile-ink) 5%, var(--pl-tile-face));
  color: var(--pl-tile-ink-soft); font-size: 13px; line-height: 1; }
.pl-adotd-close:hover { color: var(--pl-tile-ink); }
.pl-adotd-close:active { transform: scale(.94); }
.pl-adotd-close:focus-visible { outline: 3px solid var(--pl-focus, #2B7DE9); outline-offset: 2px; }
.pl-adotd-link { display: block; color: inherit; text-decoration: none; border-radius: 18px; }
.pl-adotd-link:focus-visible { outline: 3px solid var(--pl-focus, #2B7DE9); outline-offset: 2px; }
/* the specimen frame: a picture on a wall — a hairline border,
   a subtle matte tinted from the tile vars, and the whole photo
   always visible inside it (object-fit: contain; cover would
   crop the specimen, so it is never used here) */
.pl-adotd-fig { margin: 0 auto; max-width: 560px; }
.pl-adotd-tile { margin: 0 auto; max-width: 560px; }
.pl-adotd-frame { aspect-ratio: 16 / 10; box-sizing: border-box; display: grid; place-items: center;
  overflow: hidden; border: 1px solid var(--edge-soft); border-radius: 16px; padding: 10px;
  background: color-mix(in srgb, var(--pl-tile-ink) 6%, var(--pl-tile-face));
  box-shadow: var(--pl-tile-shadow); }
.pl-adotd-img { display: block; width: 100%; height: 100%; object-fit: contain;
  opacity: 0; transition: opacity .35s var(--ease); }
.pl-adotd-img.is-loaded { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .pl-adotd-img { transition: none; } }
html[data-motion="reduced"] .pl-adotd-img { transition: none; }
/* the caption block: below the frame, never on it */
.pl-adotd-cap { display: block; margin: 0; padding: 10px 2px 0; }
.pl-adotd-headline { display: block; font-size: 16px; font-weight: 800; line-height: 1.35;
  letter-spacing: -.01em; color: var(--pl-tile-ink); }
.pl-adotd-caption { display: block; font-size: 14px; line-height: 1.5; color: var(--pl-tile-ink-soft); }
.pl-adotd-headline + .pl-adotd-caption { margin-top: 2px; }
/* the no-photo tile: the glyph is the visual, centered in the
   same frame box, headline + caption under it (the .pl-adotd-cap
   block above) */
.pl-adotd-glyph { font-family: var(--font-display, inherit); font-size: clamp(72px, 22vmin, 148px);
  font-weight: 800; line-height: 1; color: var(--pl-tile-ink); }
/* ==== /AD OF THE DAY ==== */
/* ==== $8 CARD — BOT MANNERS SCHOOL (§64, 2026-10-23, Victor's words: "a thing
   that's real fucking nice" on each lad's own page) ====
   A first-class card in the home column, in the shell's own idiom: the
   Ad of the Day's width and frame, the shell's tile vars, no artwork,
   no overlay — the account, the help, and where you pay. One card, all
   four pages; personalization is data only. The honest line carries
   no lock-in: cancelling reads as welcome. */
.pl-bms { flex: none; width: min(1060px, calc(100% - 20px)); margin: 0 auto 10px;
  box-sizing: border-box; padding: 18px 18px 16px;
  border: 1px solid var(--edge-soft); border-radius: 18px;
  background: var(--pl-tile-face); color: var(--pl-tile-ink);
  box-shadow: var(--pl-tile-shadow); }
.pl-bms-kicker { font-size: 11px; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: var(--pl-tile-ink-soft); }
.pl-bms-title { margin: 4px 0 0; font-size: 21px; font-weight: 800; line-height: 1.25; letter-spacing: -.01em; }
.pl-bms-line { margin: 6px 0 0; font-size: 15px; line-height: 1.5; color: var(--pl-tile-ink-soft); }
.pl-bms-list { margin: 12px 0 0; padding: 0; list-style: none; }
.pl-bms-list li { padding: 6px 0 6px 24px; position: relative; font-size: 14.5px; font-weight: 600;
  border-top: 1px solid var(--pl-line, var(--edge-soft)); }
.pl-bms-list li::before { content: "✓"; position: absolute; left: 2px; top: 6px; font-weight: 800; }
.pl-bms-foot { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-top: 14px; }
.pl-bms-price { font-size: 20px; font-weight: 800; letter-spacing: -.01em; white-space: nowrap; }
.pl-bms-cta { display: inline-block; padding: 12px 20px; border-radius: 999px; text-decoration: none;
  font-size: 15px; font-weight: 800; white-space: nowrap;
  background: var(--pl-tile-ink); color: var(--pl-tile-face); }
.pl-bms-cta:active { transform: scale(.97); }
.pl-bms-cta:focus-visible { outline: 3px solid var(--pl-focus, #2B7DE9); outline-offset: 2px; }
.pl-bms-honest { margin: 12px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--pl-tile-ink-soft); }
/* ==== /$8 CARD ==== */
/* ==== INSTANCE HERO (§42 graft, 2026-10-23 — the Shed graft) ====
   An instance may declare a hero in its data (the publisher dresses
   it into his entry, generation-time only, like the §64 card above).
   It is his front door as it was designed before the shell flip: his
   own photograph as a framed block, his title and greeting BELOW it
   — copy never sits on the photo (the no-overlay law) — and his
   section key-line as a caption. Inert on every surface that does
   not declare one: no element, no rules engage. The look rides his
   skin pack's tokens (--pl-*) and display face when he wears one. */
.pl-hero { flex: none; width: min(1060px, calc(100% - 20px)); margin: 0 auto 10px;
  box-sizing: border-box; color: var(--pl-tile-ink); }
.pl-hero-img { display: block; width: 100%; height: 15rem; object-fit: cover;
  border: 1px solid var(--edge-soft); border-radius: 18px; box-shadow: var(--pl-tile-shadow); }
.pl-hero-copy { padding: 14px 4px 2px; }
.pl-hero-title { margin: 0; font-family: var(--pl-skin-font-display, var(--font-display, inherit));
  font-size: 34px; font-weight: 800; line-height: 1.15; letter-spacing: -.01em; }
.pl-hero-greet { margin: 6px 0 0; font-size: 17px; line-height: 1.45; color: var(--pl-tile-ink-soft); }
.pl-hero-keys { margin: 8px 0 0; font-size: 12px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--pl-tile-ink-soft); }
/* Typographic hero (all-lads fun pass, 2026-10-23): a lad whose data
   declares a hero but no photo — none is resident and none is ever
   fabricated — gets his words as a dressed band in his own skin
   tokens: his sky gradient, his tile rim and shadow. Inert unless a
   .pl-hero-type element exists (Mason, Caleb); the photo form above
   is untouched. */
.pl-hero-type .pl-hero-copy { background: linear-gradient(180deg, var(--pl-sky-top), var(--pl-sky-low));
  border: 1px solid var(--pl-tile-rim, var(--edge-soft)); border-radius: 18px;
  box-shadow: var(--pl-tile-shadow); padding: 20px 18px 16px; }
/* Hero dressing (win-back pass, 2026-10-23): a hero whose data
   declares "deco" wears its lad's original band furniture — for
   Mason ("ironwork", mined verbatim from his shipped page): the
   gaslamp row across the band, the ironwork ornament above his
   eyebrow, and the brass-diamond rule under his key-line. Every
   piece is an element composed inside the band, beside the words;
   nothing is an image with copy laid over it. The brass rides his
   skin's focus token (his #C9A227) via currentColor. The lamps take
   his original positions and flicker delays (12/30/52/71/88%,
   0/1.3/.6/2.1/2.8s); reduced motion stills them. Inert unless a
   .pl-hero-deco element exists. */
.pl-hero.pl-hero-deco { position: relative; }
.pl-hero-deco .pl-hero-copy { text-align: center; padding-top: 34px; }
.pl-hero-eyebrow { margin: 0 0 8px; font-size: 12px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--pl-badge, inherit); }
.pl-hero-deco .pl-hero-title { font-weight: 400; letter-spacing: .02em; }
.pl-hero-lede { margin: 8px auto 0; font-size: 14.5px; line-height: 1.5;
  max-width: 38ch; color: var(--pl-tile-ink-soft); }
.pl-hero-deco .pl-hero-keys { max-width: 46ch; margin-left: auto; margin-right: auto; }
.pl-hero-lamps { position: absolute; top: 8px; left: 0; right: 0; height: 20px;
  pointer-events: none; }
.pl-hero-lamps span { position: absolute; top: 0; width: 13px; height: 19px;
  margin-left: -6px; border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%;
  background: radial-gradient(50% 50% at 50% 62%, #FFE9BD 0 26%, #F2C14E 55%, rgba(242,193,78,0) 80%);
  animation: pl-lamp-flicker 3.4s ease-in-out infinite; }
.pl-hero-lamps span:nth-child(1) { left: 12%; }
.pl-hero-lamps span:nth-child(2) { left: 30%; animation-delay: 1.3s; }
.pl-hero-lamps span:nth-child(3) { left: 52%; animation-delay: .6s; }
.pl-hero-lamps span:nth-child(4) { left: 71%; animation-delay: 2.1s; }
.pl-hero-lamps span:nth-child(5) { left: 88%; animation-delay: 2.8s; }
@keyframes pl-lamp-flicker { 0%, 100% { opacity: .95; transform: scale(1); }
  50% { opacity: .72; transform: scale(.93); } }
@media (prefers-reduced-motion: reduce) { .pl-hero-lamps span { animation: none; } }
.pl-hero-iron { display: flex; justify-content: center; margin: 0 0 12px;
  color: var(--pl-focus, #C9A227); opacity: .9; }
.pl-hero-iron svg { width: 220px; height: 34px; }
.pl-hero-rule { display: flex; justify-content: center; margin-top: 12px;
  color: var(--pl-focus, #C9A227); }
.pl-hero-rule svg { width: 26px; height: 26px; }
/* ==== /INSTANCE HERO ==== */


/* ==== SHELF PHONE FIT (§55, 2026-10-23 — Victor's screenshot) ====
   tide.css centres the clock cluster absolutely (.pl-clock-center,
   left: 50%) on the assumption of two orbs a side. The shelf
   actually carries THREE orbs on the left (back, home, search) and
   two on the right — at phone widths the centred clock slid under
   the search orb, its magnifier drawn through the time digits
   (measured on Michael's page at 390px: 1,018 px² of overlap,
   643 px² of it over the digits themselves). The fix lives here,
   in the shell the four lad pages share, not in tide.css (which
   every other surface also wears): on phones the clock joins the
   flow as the middle item, the spacer and the brand stand down,
   and at the narrowest widths the orbs take the house's small
   44px size — the size the sheet heads already use. Wide screens
   keep the true-centre float, untouched. */
@media (max-width: 700px) {
  .pl-shelf { justify-content: space-between; }
  .pl-shelf .pl-spacer, .pl-shelf .pl-shelf-brand { display: none; }
  .pl-clock-center { position: static; transform: none; flex: 0 1 auto; min-width: 0; }
}
@media (max-width: 480px) {
  .pl-shelf { padding-inline: 10px; }
  .pl-shelf .pl-orb { width: 44px; height: 44px; }
  .pl-clock-center .pl-clock-time { font-size: 21px; }
}
/* ==== /SHELF PHONE FIT ==== */
/* The Midday Game board, native in the room (F1): standings read
   live from the game's own feed, in the shell's own type. */
.pl-mgboard-list { display: flex; flex-direction: column; margin-top: 6px; }
.pl-mgboard-row { display: flex; align-items: baseline; gap: 10px; padding: 7px 2px; border-bottom: 1px solid var(--pl-line); font-size: 14.5px; }
.pl-mgboard-row:last-child { border-bottom: 0; }
.pl-mgboard-rank { font-weight: 800; color: var(--pl-ink-soft); min-width: 1.2em; }
.pl-mgboard-name { font-weight: 700; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-mgboard-rounds { color: var(--pl-ink-soft); font-variant-numeric: tabular-nums; font-size: 13px; }
.pl-mgboard-total { font-weight: 800; font-variant-numeric: tabular-nums; }
.pl-mg-room { min-width: 0; }
/* ==== §71 FEATURE ROOMS — WORD OF THE DAY + TIT FIT LOG (2026-10-23
   night, the Tit pass): the lad's own original card grammar — coral
   pick panel, sunken stat chips, hairline rows, check rows — carried
   in shell vocabulary on skin tokens, so any instance wearing the
   data gets the grammar. ==== */
.pl-pick { border: 1px solid var(--pl-badge); background: color-mix(in srgb, var(--pl-badge) 7%, var(--pl-tile-face)); border-radius: 12px; padding: 12px 14px; margin-top: 8px; }
.pl-pick-origin { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: var(--pl-tile-ink-soft); }
.pl-wotd-term { font-family: var(--pl-skin-font-display, inherit); font-size: 30px; font-weight: 800; line-height: 1.15; color: var(--pl-tile-ink); margin-top: 4px; }
.pl-wotd-line { font-size: 13.5px; line-height: 1.5; color: var(--pl-tile-ink); margin-top: 6px; }
.pl-wotd-flavor { font-size: 13px; line-height: 1.5; color: var(--pl-tile-ink-soft); margin-top: 8px; font-style: italic; }
.pl-sparkline { font-size: 16.5px; font-weight: 700; line-height: 1.45; color: var(--pl-tile-ink); margin-top: 6px; }
.pl-wotd-list { margin-top: 12px; border-top: 1px solid var(--edge-soft); }
.pl-wotd-list-h { font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: var(--pl-tile-ink-soft); margin: 10px 0 2px; }
.pl-wotd-row { display: flex; gap: 10px; align-items: baseline; padding: 7px 0; border-bottom: 1px solid var(--edge-soft); }
.pl-wotd-row:last-child { border-bottom: 0; }
.pl-wotd-row-t { font-weight: 700; color: var(--pl-tile-ink); white-space: nowrap; }
.pl-wotd-row-m { flex: 1 1 auto; min-width: 0; font-size: 13px; color: var(--pl-tile-ink-soft); }
.pl-wotd-row-tag { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--pl-badge); }
.pl-chiprow { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.pl-stat { background: color-mix(in srgb, var(--pl-tile-ink) 6%, var(--pl-tile-face)); border: 1px solid var(--edge-soft); border-radius: 999px; padding: 5px 11px; font-size: 13px; color: var(--pl-tile-ink); }
.pl-stat b { font-variant-numeric: tabular-nums; }
.pl-card-acts input[type="date"] { min-height: 44px; font: inherit; font-size: 14px; border-radius: 10px; border: 1px solid var(--edge-soft); padding: 8px 10px; background: var(--pl-tile-face); color: var(--pl-tile-ink); }
.pl-titlog-list { margin-top: 10px; border-top: 1px solid var(--edge-soft); }
.pl-titlog-row { display: flex; gap: 10px; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--edge-soft); }
.pl-titlog-row:last-child { border-bottom: 0; }
.pl-titlog-check { flex: none; width: 40px; height: 40px; /* P12: was 30x30 — rendered 30x30 in Michael's Tit Fit log with seeded rows (hunt3 rig, both engines) */ border-radius: 8px; border: 1.5px solid var(--edge-soft); background: var(--pl-tile-face); color: var(--pl-on-badge); font-size: 16px; font-weight: 800; cursor: pointer; display: grid; place-items: center; padding: 0; }
.pl-titlog-row.is-done .pl-titlog-check { background: var(--pl-badge); border-color: var(--pl-badge); }
.pl-titlog-mid { flex: 1 1 auto; min-width: 0; }
.pl-titlog-what { font-weight: 600; color: var(--pl-tile-ink); }
.pl-titlog-when { font-size: 12px; color: var(--pl-tile-ink-soft); font-variant-numeric: tabular-nums; }
.pl-titlog-del { flex: none; width: 40px; height: 40px; /* P12: was 30x30 — same hunt3 finding as .pl-titlog-check */ border: 0; background: transparent; color: var(--pl-tile-ink-soft); cursor: pointer; font-size: 13px; padding: 0; }
/* ==== §72 FEATURE ROOMS — CLIMB TONIGHT + DISC PICK (2026-10-23
   night, Workstream B): Mason's glance card wears his original
   card's grammar in shell vocabulary — the brass-washed panel
   (his .ct card: gradient wash, brass hairline), hairline rows,
   the coral when-line, the round 44px goal-done buttons (his
   .cg-done) — all on skin tokens, so the night pack colors it. ==== */
.pl-climb { border: 1px solid var(--pl-tile-rim); background: linear-gradient(160deg, color-mix(in srgb, var(--pl-focus) 13%, var(--pl-tile-face)), color-mix(in srgb, var(--pl-badge) 7%, var(--pl-tile-face)) 55%, var(--pl-tile-face)); border-radius: 12px; padding: 12px 14px; margin-top: 8px; }
.pl-climb-date { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .34em; color: var(--pl-focus); margin: 0; }
.pl-climb-row { font-size: 15px; line-height: 1.5; color: var(--pl-tile-ink); padding: 10px 0 0; margin-top: 10px; border-top: 1px solid var(--pl-tile-rim); }
.pl-climb-row b { font-weight: 700; }
.pl-climb-when { color: var(--pl-badge); font-weight: 700; white-space: nowrap; }
.pl-climb-row a { color: var(--pl-focus); font-weight: 600; }
.pl-climb-focus { font-size: 13.5px; line-height: 1.45; color: var(--pl-tile-ink-soft); margin: 10px 0 0; }
.pl-climb-focus b { color: var(--pl-focus); }
.pl-climb-meter { margin-top: 10px; }
.pl-stat.is-full { background: var(--pl-focus); border-color: var(--pl-focus); color: var(--pl-tile-face); }
.pl-climb-last { font-size: 13px; line-height: 1.5; color: var(--pl-tile-ink-soft); margin: 10px 0 0; }
.pl-climb-cta { display: inline-flex; align-items: center; min-height: 44px; margin-top: 12px; padding: 10px 18px; border-radius: 999px; border: 0; background: var(--pl-badge); color: var(--pl-on-badge); font: inherit; font-size: 14px; font-weight: 700; letter-spacing: .04em; cursor: pointer; }
.pl-climb-goal { display: flex; gap: 10px; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--edge-soft); }
.pl-climb-goal:last-child { border-bottom: 0; }
.pl-climb-num { flex: none; font-weight: 800; color: var(--pl-tile-ink-soft); font-variant-numeric: tabular-nums; }
.pl-climb-input { flex: 1 1 auto; min-width: 0; min-height: 44px; font: inherit; font-size: 16px; border-radius: 10px; border: 1px solid var(--edge-soft); padding: 8px 10px; background: var(--pl-tile-face); color: var(--pl-tile-ink); }
.pl-climb-input.is-done { text-decoration: line-through; opacity: .55; }
.pl-climb-done { flex: none; width: 44px; height: 44px; border-radius: 50%; border: 1.5px solid var(--pl-tile-rim); background: transparent; color: var(--pl-tile-face); font-size: 17px; cursor: pointer; display: grid; place-items: center; padding: 0; }
.pl-climb-done.is-done { background: var(--pl-focus); border-color: var(--pl-focus); }
.pl-discpick-text { font-size: 16.5px; font-weight: 700; line-height: 1.45; color: var(--pl-tile-ink); margin-top: 6px; }
/* ==== §73 STRUCTURED CHECKLIST (2026-10-24 night, UI campaign
   Wave 2 — UI-02 seam (l) generalized): the lad's original .cc-*
   checklist grammar in shell vocabulary — status line, NEXT line,
   sunken chips (the .pl-stat row above), a progress track whose
   fill is the working coral (--pl-badge, his done-check fill), and
   full-width tappable check rows: hairline-divided, a 30px box that
   fills coral when done, the label striking soft when done, and
   the full-sweep celebration in the badge color. All on skin
   tokens, so any instance wearing the data gets the grammar in
   its own look, light + dark. ==== */
.pl-check-status { font-size: 13px; line-height: 1.5; color: var(--pl-tile-ink-soft); margin-top: 6px; }
.pl-check-status b { color: var(--pl-tile-ink); }
.pl-check-next { font-size: 13.5px; line-height: 1.5; color: var(--pl-tile-ink); margin-top: 4px; }
.pl-check-next b { font-weight: 800; text-transform: uppercase; letter-spacing: .06em; font-size: 11px; color: var(--pl-tile-ink-soft); }
.pl-check-progress { height: 6px; border-radius: 999px; background: color-mix(in srgb, var(--pl-tile-ink) 10%, var(--pl-tile-face)); margin-top: 10px; overflow: hidden; }
.pl-check-fill { display: block; height: 100%; width: 0; border-radius: 999px; background: var(--pl-badge); transition: width .25s ease; }
.pl-check-list { margin-top: 6px; }
.pl-check-row { display: flex; gap: 10px; align-items: center; width: 100%; min-height: 44px; padding: 8px 0; border: 0; border-bottom: 1px solid var(--edge-soft); background: transparent; font: inherit; text-align: left; cursor: pointer; color: var(--pl-tile-ink); }
.pl-check-row:last-child { border-bottom: 0; }
.pl-check-box { flex: none; width: 30px; height: 30px; border-radius: 8px; border: 1.5px solid var(--edge-soft); background: var(--pl-tile-face); color: var(--pl-on-badge); font-size: 16px; font-weight: 800; display: grid; place-items: center; padding: 0; }
/* P12: the BUTTON form of the check box (the gram tick-total + grocery toggles — a standalone aria-pressed control, app.js) takes the 40px floor. The span form above stays 30px: it is aria-hidden decoration inside the full-width .pl-check-row button, which is the real target (hunt3 census, Round 12). */
button.pl-check-box { width: 40px; height: 40px; }
.pl-check-row.is-done .pl-check-box { background: var(--pl-badge); border-color: var(--pl-badge); }
.pl-check-label { flex: 1 1 auto; min-width: 0; font-size: 14.5px; line-height: 1.4; font-weight: 600; }
.pl-check-row.is-done .pl-check-label { color: var(--pl-tile-ink-soft); }
.pl-check-celebrate { font-size: 14.5px; line-height: 1.5; font-weight: 700; color: var(--pl-badge); margin-top: 10px; }
.pl-check-entries { margin-top: 10px; border-top: 1px solid var(--edge-soft); }
/* ==== §74 TILE-FACE WORKING LINES (2026-10-24 night, UI campaign
   Wave 3 — UI-02 seam (k)): the §71–§73 card grammar on the tile
   face, in the same shell vocabulary — a status line, a NEXT line
   (his .cc-next: small caps label + the step, wrapping whole,
   never ellipsised), and sunken .pl-stat chips at face size. The
   label becomes a column ONLY on a tile whose data declares a
   face (c29-channel.pl-has-face, seated by the §74 decorator);
   every other tile's label is byte-for-byte the row it was. The
   tile's outer box never changes: on desktop the preview gives
   the height, on phone the label's scrim deepens a touch earlier
   so the working lines sit on the tile's own face colour, not on
   the scene art. All on skin tokens, light + dark. ==== */
c29-channel.pl-has-face .pl-tile-label { flex-direction: column; align-items: stretch; gap: 0; }
.pl-face { display: block; margin-top: 2px; }
.pl-face-status { font-size: 12px; line-height: 1.35; font-weight: 600; color: var(--pl-tile-ink-soft); }
.pl-face-next { font-size: 12px; line-height: 1.35; font-weight: 600; color: var(--pl-tile-ink); margin-top: 1px; overflow-wrap: break-word; }
.pl-face-next b { font-weight: 800; text-transform: uppercase; letter-spacing: .06em; font-size: 10px; color: var(--pl-tile-ink-soft); }
.pl-face-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
.pl-face-chip { font-size: 11px; padding: 3px 8px; }
@media (max-width: 700px) and (orientation: portrait) {
  c29-channel.pl-has-face .pl-tile-label { background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--pl-tile-face) 96%, transparent) 32%); }
}
/* ==== §81 TILE NAMES WRAP WHOLE (2026-10-24 night, UI campaign
   Wave 21 — UI-02 seam (k) remainder, Community's name width):
   the Tide component sets .pl-tile-name to white-space:nowrap
   with NO overflow treatment (its sibling .pl-tile-sub carries
   the ellipsis) — so a name wider than the tile did not wrap and
   did not ellipsise, it simply ran past the tile's edge and was
   cut by the tile's own overflow:hidden, mid-word: Michael's
   "Community & Good Neighboring" is 245.5px of text on the 179px
   phone tile and rendered "Community & Good N". Measured on the
   Wave 12 freeze, SIX names clip across the four lads (Community
   by 82.5px; "Get 29Court connected" by 16.6px; Caleb's "This
   week in the Gundo" by 18.5px; Mason's "Your day, one glance"
   by 11.8px and "Your Tuesday sweep" by 7.1px; "Caribbean
   Immersion" by 1px). The shell's treatment, uniform for every
   tile on every surface that runs this shell: a name WRAPS
   WHOLE — never an ellipsis (a cut name is not the tile's name),
   never a per-tile shrink (one name size is the grid's rhythm) —
   balanced across its lines, breaking mid-word only when a
   single word alone exceeds the box. A name that fits keeps its
   one line untouched: at phone width the wrap trigger is the
   label's content box (147px of the 179px tile — 173px padding
   box minus 2x13px padding), NARROWER than the width names
   provably fit today (160px to the tile's inner edge), so the
   portrait label's inline padding yields 13px -> 4px a side and
   the box becomes 165px: every name that rendered whole at the
   Wave 12 freeze keeps its exact one line (the widest, Danny's
   161px "The Storm Party Bus", included), and only the six
   clipped names change — five wrap to two balanced lines,
   Caribbean Immersion takes its one line whole. The vertical
   padding is untouched, so a one-line label's height — and every
   §74 face label's height — is byte-for-byte the height it was;
   a wrapped name's label grows only by its second line. All on
   the shell's own sheet, after the component sheet, so the
   component itself is untouched and every consumer of THIS
   shell inherits the treatment. ==== */
.pl-tile-name { white-space: normal; overflow-wrap: break-word; min-width: 0; text-wrap: balance; }
@media (max-width: 700px) and (orientation: portrait) {
  .pl-tile-label { padding-left: 4px; padding-right: 4px; }
}
/* ==== §75 TODAY-BOARD (2026-10-24 night, UI campaign Wave 4 —
   UI-02 seam (m)): his original .sx-today-list grammar in the
   §71–§73 shell vocabulary — a mono uppercase key, the line's
   value set semibold, hairline-divided rows, every row a full
   tappable jump (>=44px). All on skin tokens, light + dark. ==== */
.pl-today-date { font-size: 12px; line-height: 1.4; font-weight: 700; letter-spacing: .04em; color: var(--pl-tile-ink-soft); margin-top: 6px; }
.pl-today-list { margin-top: 6px; }
.pl-today-row { display: flex; gap: 12px; align-items: baseline; width: 100%; min-height: 44px; padding: 10px 0; border: 0; border-bottom: 1px solid var(--edge-soft); background: transparent; font: inherit; text-align: left; cursor: pointer; color: var(--pl-tile-ink); }
.pl-today-row:last-child { border-bottom: 0; }
.pl-today-k { flex: none; width: 104px; font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--pl-tile-ink-soft); padding-top: 2px; }
.pl-today-v { flex: 1 1 auto; min-width: 0; font-size: 14.5px; line-height: 1.4; font-weight: 600; overflow-wrap: break-word; }
/* ==== §76 STICKY CHIP NAV (2026-10-24 night, UI campaign Wave 5 —
   UI-02 seam (n)): his original .sx-nav grammar in the §71–§75
   shell vocabulary — a sticky blurred band at the head of the
   home column (the hero's own width, so its edges line up with
   the hero and the grid), a horizontally scrolling pill list
   with the scrollbar hidden (the LIST scrolls; the page never
   does), chips at his original 2.5rem floor on the tile face
   with a hairline rim, semibold ink-soft resting and full ink +
   strong rim on hover. There is deliberately NO [aria-current]
   treatment: the shell carries no scroll-spy (see §76 in app.js),
   so no chip ever wears the sunken "current" dress his original
   reserved for the spied section. All on skin tokens (the band
   rides --pl-bar, the shell's own blurred-bar token), light +
   dark. Inert on every surface that declares no nav data: no
   element, no rules engage. ==== */
.pl-chipnav { flex: none; position: sticky; top: 0; z-index: 20; width: min(1060px, calc(100% - 20px)); margin: 0 auto 10px;
  box-sizing: border-box; padding: 8px 10px; border: 1px solid var(--pl-bar-edge, var(--edge-soft)); border-radius: 16px;
  background: var(--pl-bar, var(--pl-tile-face)); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
/* F3 PERF R3 (2026-10-25, pleasant-performance): scroll-degrade — the
   sticky chip nav rides INSIDE the scroller, so its backdrop moves with
   the content: blur stands down while scrolling, returns at rest (see
   the .pl-scrolling driver in app.js). */
.pl-stage.pl-scrolling .pl-chipnav { backdrop-filter: none; -webkit-backdrop-filter: none; }
.pl-chipnav-list { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.pl-chipnav-list::-webkit-scrollbar { display: none; }
.pl-chipnav-chip { flex: none; display: inline-flex; align-items: center; min-height: 40px; padding: 0 14px;
  border: 1px solid var(--edge-soft); border-radius: 999px; background: var(--pl-tile-face); color: var(--pl-tile-ink-soft);
  font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.pl-chipnav-chip:hover { color: var(--pl-tile-ink); border-color: var(--pl-tile-rim); }
/* ==== §77 WEATHER ROOM (2026-10-24 night, UI campaign Wave 6 —
   UI-02 seams (m)+(n) remainder): his original #wx-banner card's
   grammar in the §71–§76 shell vocabulary — the cove art as a
   framed element at the card's head (beside the words in his
   original's wide layout, above them at phone width; never an
   overlay), the ds-overline in mono caps, the big temp line, the
   forecast in ink-soft, the sunken .pl-stat chips (the §73 row),
   the muted status line, and the board door as a full 44px
   badge-filled pill (the .pl-climb-cta posture). The staged
   card renders his unavailable state only (see §77 in app.js);
   there is no loading dress here because nothing is loading.
   All on skin tokens, light + dark. Inert on every surface
   that declares no weather data. ==== */
.pl-wx-art { display: block; width: 100%; height: 132px; object-fit: cover; border-radius: 10px; margin-bottom: 10px; }
.pl-wx-over { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--pl-tile-ink-soft); margin: 0; }
.pl-wx-temp { font-size: 27px; line-height: 1.2; font-weight: 800; color: var(--pl-tile-ink); margin-top: 4px; }
.pl-wx-forecast { font-size: 14.5px; line-height: 1.5; color: var(--pl-tile-ink-soft); margin: 6px 0 0; }
.pl-wx-status { font-size: 13px; line-height: 1.5; color: var(--pl-tile-ink-soft); margin: 10px 0 0; }
.pl-wx-hours { display: flex; flex-wrap: wrap; gap: 6px; }
/* D-B1 fix (P1-B send-back, 2026-10-24 — overseer GRADE §6): a
   board door's exit chip is nowrap (253.88px for this host) and
   cannot share the label's flex row — stamped inline it burst the
   pill past its card and the 390px viewport and crushed the label
   to four lines. The pill now stacks (the E-12 posture): label on
   its own line, the chip whole on its own line below it, the pill
   capped at its card's width. Same posture on .pl-storm-door. */
.pl-wx-door { display: inline-flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 6px; max-width: 100%; box-sizing: border-box; min-height: 44px; margin-top: 12px; padding: 10px 18px; border-radius: 999px; background: var(--pl-badge); color: var(--pl-on-badge); font-size: 14px; font-weight: 700; letter-spacing: .04em; text-decoration: none; }
.pl-wx-door .xl-tag.pl-ext-inline { margin-left: 0; }
/* ==== §78 STORM WATCH ROOM (2026-10-24 night, UI campaign Wave 7 —
   UI-02 seam (l) general grammar, next instance): his original
   Storm watch card's grammar in the §71–§77 shell vocabulary —
   the head/badge + NEXT line reuse §73's .pl-check-status /
   .pl-check-next outright, the baked season line set plain, the
   live line in ink-soft (it carries his unavailable state, see
   §78 in app.js), and the board door as a full 44px badge-filled
   pill (the .pl-wx-door posture) with his trailing words beside
   it in ink-soft. All on skin tokens, light + dark. Inert on
   every surface that declares no storms data. ==== */
.pl-storm-season { font-size: 14.5px; line-height: 1.5; color: var(--pl-tile-ink); margin: 8px 0 0; }
.pl-storm-live { font-size: 14.5px; line-height: 1.5; color: var(--pl-tile-ink-soft); margin: 6px 0 0; }
.pl-storm-doorwrap { margin: 0; }
.pl-storm-door { display: inline-flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 6px; max-width: 100%; box-sizing: border-box; min-height: 44px; margin-top: 12px; padding: 10px 18px; border-radius: 999px; background: var(--pl-badge); color: var(--pl-on-badge); font-size: 14px; font-weight: 700; letter-spacing: .04em; text-decoration: none; }
.pl-storm-door .xl-tag.pl-ext-inline { margin-left: 0; }
.pl-storm-door-note { display: block; margin-top: 6px; font-size: 14.5px; line-height: 1.5; color: var(--pl-tile-ink-soft); }
/* ==== §79 COMMUNITY ROOM (2026-10-24 night, UI campaign Wave 8 —
   UI-02 seam (l) general grammar, next instance): his original
   Community card's baked entry-list grammar in the §71–§78 shell
   vocabulary — the head/badge + NEXT line reuse §73's
   .pl-check-status / .pl-check-next outright, the section
   headings set as quiet subheads, the market rows hairline-
   divided with the name in full ink and the day/time/place line
   riding the same line, and the two baked paragraphs in ink-soft
   (his card's own .cc-baked paragraph posture). All on skin
   tokens, light + dark. Inert on every surface that declares no
   community data. ==== */
.pl-comm-h { font-size: 13px; line-height: 1.4; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--pl-tile-ink); margin: 12px 0 0; }
.pl-comm-list { list-style: none; margin: 4px 0 0; padding: 0; }
.pl-comm-row { font-size: 14.5px; line-height: 1.5; color: var(--pl-tile-ink-soft); padding: 8px 0; border-bottom: 1px solid var(--edge-soft); }
.pl-comm-row:last-child { border-bottom: 0; }
.pl-comm-row b { color: var(--pl-tile-ink); font-weight: 700; }
.pl-comm-p { font-size: 14.5px; line-height: 1.5; color: var(--pl-tile-ink-soft); margin: 6px 0 0; }
/* ==== §80 DISC GOLF ROOM (2026-10-24 night, UI campaign Wave 9 —
   UI-02 seam (l) general grammar, next instance): his original
   Disc golf card's baked board grammar in the §71–§79 shell
   vocabulary — the head/badge + NEXT line reuse §73's
   .pl-check-status / .pl-check-next outright and the course /
   perch lists reuse §79's .pl-comm-* outright; the one new rule
   is the course rows' own UDisc link (his card carried the link
   inline in each row), set in the shell's focus ink with his
   original's tap padding (the R16 floor his page gave these
   links). All on skin tokens, light + dark. Inert on every
   surface that declares no discgolf data. ==== */
.pl-dg-link { color: var(--pl-focus); font-weight: 600; display: inline-block; padding: .45rem 0; }
/* ==== MIDDAY GAME, NATIVE IN THE SHELL (Fleet F1, 2026-10-23) ====

   The game's own styles, re-scoped under .pl-mg-room by

   /tmp/f1/build_mg_css.py from its canonical sources

   (midday-game/index.html <style>, design-system tokens +

   the .ds-* component rules the game uses). Regenerate,

   don't hand-edit. The room's theme button rests: the shell

   owns the theme here. */

/* --29d-* bridge: the game's palette, living on the room.
   Values copied from design-system/tokens.css (light + dark). */
.pl-mg-room {
  --29d-coral-50: #FFF4EE;
  --29d-coral-100: #FFE4D4;
  --29d-coral-200: #FFC8A6;
  --29d-coral-300: #FF9E70;
  --29d-coral-400: #FB7E54;
  --29d-coral-500: #F46036;
  --29d-coral-600: #C7471F;
  --29d-coral-700: #B03D1C;
  --29d-coral-800: #8A3018;
  --29d-coral-900: #652412;
  --29d-text-1: #1E2A30;
  --29d-text-2: #46535A;
  --29d-text-3: #5C686E;
  --29d-text-4: #5C686E;
  --29d-text-5: #CFD1CC;
  --29d-bg: #F5EFE3;
  --29d-surface: #FBF7EF;
  --29d-raised: #FFFDF8;
  --29d-overlay: #FFFDF8;
  --29d-sunken: #ECE3D2;
  --29d-wash: color-mix(in srgb, var(--29d-text-1) 6%, transparent);
  --29d-wash-2: color-mix(in srgb, var(--29d-text-1) 10%, transparent);
  --29d-border: #E2D6C0;
  --29d-border-strong: #CDBEA3;
  --29d-ring: color-mix(in srgb, var(--29d-text-1) 14%, transparent);
  --29d-blue-100: #E2F0FE;
  --29d-blue-600: #2E7FDB;
  --29d-blue-700: #1F63B4;
  --29d-green-100: #DFF3E5;
  --29d-green-600: #267A43;
  --29d-green-700: #20693A;
  --29d-amber-100: #FBEFD8;
  --29d-amber-600: #B07414;
  --29d-amber-700: #8F5D10;
  --29d-red-100: #FBE6E3;
  --29d-red-500: #F56C6C;
  --29d-red-600: #BC4038;
  --29d-red-700: #A93232;
  --29d-teal-600: #2A7C71;
  --29d-teal-100: #DAEFE9;
  --29d-gold-500: #E9A13B;
  --29d-gold-600: #C77F1A;
  --29d-on-coral: #FFFFFF;
  --29d-on-dark: #FFFFFF;
  --29d-font-ui: -apple-system, BlinkMacSystemFont, "Inter", "SF Pro Text",
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --29d-font-display: "Nunito", ui-rounded, -apple-system, "SF Pro Rounded", "Segoe UI", sans-serif;
  --29d-font-mono: ui-monospace, "JetBrains Mono", "SF Mono", SFMono-Regular,
    Menlo, Consolas, monospace;
  --29d-font-features: "ss03", "cv11", "tnum" 0;
  --29d-text-2xs: 11px;
  --29d-lh-2xs: 16px;
  --29d-text-xs: 12px;
  --29d-lh-xs: 16px;
  --29d-text-sm: 13px;
  --29d-lh-sm: 20px;
  --29d-text-md: 15px;
  --29d-lh-md: 24px;
  --29d-text-lg: 17px;
  --29d-lh-lg: 26px;
  --29d-text-xl: 20px;
  --29d-lh-xl: 28px;
  --29d-text-2xl: 24px;
  --29d-lh-2xl: 32px;
  --29d-text-3xl: 32px;
  --29d-lh-3xl: 40px;
  --29d-text-4xl: 40px;
  --29d-lh-4xl: 48px;
  --29d-weight-regular: 400;
  --29d-weight-medium: 500;
  --29d-weight-semibold: 600;
  --29d-weight-bold: 700;
  --29d-weight-xbold: 800;
  --29d-r-1: 4px;
  --29d-r-2: 6px;
  --29d-r-3: 8px;
  --29d-r-4: 12px;
  --29d-pill: 999px;
  --29d-s-0: 2px;
  --29d-s-1: 4px;
  --29d-s-2: 8px;
  --29d-s-3: 12px;
  --29d-s-4: 16px;
  --29d-s-6: 24px;
  --29d-s-8: 32px;
  --29d-s-12: 48px;
  --29d-s-16: 64px;
  --29d-shadow-pop: 0 0 0 1px var(--29d-ring),
    0 8px 24px rgba(28, 25, 23, 0.10),
    0 2px 6px rgba(28, 25, 23, 0.06);
  --29d-shadow-modal: 0 0 0 1px var(--29d-ring),
    0 24px 64px rgba(28, 25, 23, 0.18);
  --29d-t-instant: 80ms;
  --29d-t-fast: 120ms;
  --29d-t-base: 160ms;
  --29d-t-slow: 240ms;
  --29d-t-page: 320ms;
  --29d-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  --29d-ease-pop: cubic-bezier(0.34, 1.56, 0.64, 1);
  --29d-focus-halo: 0 0 0 3px color-mix(in srgb, var(--29d-coral-500) 32%, transparent);
  --29d-focus-ring: 0 0 0 1px var(--29d-coral-500);
  --29d-body-size: var(--29d-text-md);
  --29d-body-lh: var(--29d-lh-md);
  --29d-control-h: 40px;
  --29d-control-h-sm: 32px;
  --29d-row-h: 48px;
  --29d-card-pad: var(--29d-s-6);
  --29d-section-gap: var(--29d-s-8);
  --29d-page-pad: var(--29d-s-6);
}
[data-theme="dark"] .pl-mg-room {
  --29d-coral-500: #FFA25E;
  --29d-coral-600: #FB8B4C;
  --29d-coral-700: #FFB37C;
  --29d-coral-100: #33231A;
  --29d-coral-50: #241A13;
  --29d-text-1: #EDE7DA;
  --29d-text-2: #B9C2C4;
  --29d-text-3: #87969E;
  --29d-text-4: #9AABB3;
  --29d-text-5: #33475A;
  --29d-bg: #0C1824;
  --29d-surface: #132233;
  --29d-raised: #1A2C3D;
  --29d-overlay: #1A2C3D;
  --29d-sunken: #08121C;
  --29d-wash: rgba(190, 220, 232, 0.05);
  --29d-wash-2: rgba(190, 220, 232, 0.09);
  --29d-border: rgba(196, 214, 224, 0.12);
  --29d-border-strong: rgba(196, 214, 224, 0.22);
  --29d-ring: rgba(176, 213, 224, 0.15);
  --29d-blue-100: #102A3E;
  --29d-blue-600: #8FC7EE;
  --29d-blue-700: #B9DCF7;
  --29d-green-100: #0F2A20;
  --29d-green-600: #62CF95;
  --29d-green-700: #85DDA9;
  --29d-amber-100: #2E2310;
  --29d-amber-600: #F2B04C;
  --29d-amber-700: #F7C87C;
  --29d-red-100: #341C1D;
  --29d-red-500: #F2837E;
  --29d-red-600: #F2837E;
  --29d-red-700: #FAABA3;
  --29d-teal-100: #123A37;
  --29d-teal-600: #62C9B7;
  --29d-gold-500: #F5C15C;
  --29d-gold-600: #F5C15C;
  --29d-on-coral: #2A1503;
  --29d-shadow-pop: 0 0 0 1px var(--29d-ring),
    0 12px 32px rgba(2, 10, 14, 0.50),
    0 2px 8px rgba(2, 10, 14, 0.38);
  --29d-shadow-modal: 0 0 0 1px var(--29d-ring),
    0 32px 80px rgba(2, 10, 14, 0.60);
  --29d-focus-halo: 0 0 0 3px color-mix(in srgb, var(--29d-coral-500) 38%, transparent);
}

.pl-mg-room .ds-root, .pl-mg-room .ds-root input, .pl-mg-room .ds-root button, .pl-mg-room .ds-root select, .pl-mg-room .ds-root textarea {
  font-family: var(--29d-font-ui);
  font-feature-settings: "ss03", "cv11";
}
.pl-mg-room .ds-root, .pl-mg-room .ds-root input, .pl-mg-room .ds-root select, .pl-mg-room .ds-root textarea {
  color: var(--29d-text-1);
}
.pl-mg-room .ds-root { font-size: var(--29d-body-size); line-height: var(--29d-body-lh); }
.pl-mg-room .ds-tnum { font-variant-numeric: tabular-nums; }
.pl-mg-room .ds-btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--29d-s-2); height: var(--29d-control-h);
  color: var(--29d-text-1);
  padding: 0 var(--29d-s-4); border-radius: var(--29d-r-2);
  font-size: var(--29d-body-size); font-weight: var(--29d-weight-semibold);
  line-height: 1; border: 1px solid transparent; cursor: pointer;
  transition: transform var(--29d-t-instant) var(--29d-ease),
              box-shadow var(--29d-t-fast) var(--29d-ease),
              background-color var(--29d-t-fast) var(--29d-ease),
              border-color var(--29d-t-fast) var(--29d-ease);
  white-space: nowrap; user-select: none; text-decoration: none;
}
.pl-mg-room .ds-btn:hover { transform: translateY(-1px); }
.pl-mg-room .ds-btn:active { transform: scale(0.98); }
.pl-mg-room .ds-btn:focus-visible { outline: none; box-shadow: var(--29d-focus-halo), var(--29d-focus-ring); }
.pl-mg-room .ds-btn:disabled { cursor: not-allowed; transform: none; opacity: 0.55; }
.pl-mg-room .ds-btn.ds-btn-primary { background: var(--29d-coral-600); color: var(--29d-on-coral); }
.pl-mg-room .ds-btn.ds-btn-primary:hover { background: var(--29d-coral-700); }
.pl-mg-room .ds-btn.ds-btn-secondary { background: var(--29d-teal-600); color: var(--29d-on-coral); }
.pl-mg-room .ds-btn.ds-btn-secondary:hover { background: var(--29d-teal-700); }
.pl-mg-room .ds-btn.ds-btn-outline {
  background: var(--29d-surface); color: var(--29d-text-1);
  border-color: var(--29d-border-strong);
}
.pl-mg-room .ds-btn.ds-btn-outline:hover { border-color: var(--29d-text-3); background: var(--29d-wash); }
.pl-mg-room .ds-btn.ds-btn-ghost { background: transparent; color: var(--29d-text-2); }
.pl-mg-room .ds-btn.ds-btn-ghost:hover { background: var(--29d-wash); color: var(--29d-text-1); }
.pl-mg-room .ds-btn.ds-btn-danger { background: var(--29d-red-600); color: var(--29d-on-coral); }
.pl-mg-room .ds-btn.ds-btn-danger:hover { background: var(--29d-red-700); }
.pl-mg-room .ds-btn-sm { height: var(--29d-control-h-sm); padding: 0 var(--29d-s-3); font-size: var(--29d-text-sm); }
.pl-mg-room .ds-btn .ds-spinner {
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: ds-spin 0.8s linear infinite;
}
.pl-mg-room .ds-input, .pl-mg-room .ds-select, .pl-mg-room .ds-textarea {
  height: var(--29d-control-h); padding: 0 var(--29d-s-3);
  font-size: var(--29d-body-size); color: var(--29d-text-1);
  background: var(--29d-surface); border: 1px solid var(--29d-border-strong);
  border-radius: var(--29d-r-2);
  transition: border-color var(--29d-t-fast) var(--29d-ease),
              box-shadow var(--29d-t-fast) var(--29d-ease);
}
.pl-mg-room .ds-input::placeholder { color: var(--29d-text-4); }
.pl-mg-room .ds-input:focus, .pl-mg-room .ds-select:focus, .pl-mg-room .ds-textarea:focus {
  outline: none; border-color: var(--29d-coral-500);
  box-shadow: var(--29d-focus-halo);
}
.pl-mg-room .ds-input[aria-invalid="true"] {
  border-color: var(--29d-red-500);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--29d-red-500) 25%, transparent);
}
.pl-mg-room .ds-badge-success { background: var(--29d-green-100); color: var(--29d-green-700); }
@media (prefers-reduced-motion: reduce) {
.pl-mg-room .ds-root *, .pl-mg-room .ds-root *::before, .pl-mg-room .ds-root *::after {
    animation-duration: 80ms !important; transition-duration: 80ms !important;
  }
}
.pl-mg-room .ds-datatable-toolbar .ds-input { max-width: 280px; }
.pl-mg-room .ds-bulkactions .ds-btn { flex: 0 0 auto; }
.pl-mg-room .ds-input[type="date"] { color-scheme: light; font-variant-numeric: tabular-nums; }
.pl-mg-room [data-theme="dark"] .ds-input[type="date"] { color-scheme: dark; }

.pl-mg-room .mg {
    --mg-yellow: #FFC72C;
    --mg-ink: #171310;
    --mg-yellow-deep: color-mix(in srgb, var(--mg-yellow) 76%, var(--mg-ink));
  }
.pl-mg-room, .pl-mg-room *, .pl-mg-room *::before, .pl-mg-room *::after { box-sizing: border-box; margin: 0; padding: 0; }
.pl-mg-room { background: var(--29d-bg); color: var(--29d-text-1); font-family: var(--29d-font-ui); font-feature-settings: var(--29d-font-features); }
.pl-mg-room .wrap { max-width: 560px; margin: 0 auto; padding: var(--29d-s-3) var(--29d-s-3) var(--29d-s-12); }
.pl-mg-room .bug-mount { position: sticky; top: var(--29d-s-2); z-index: 40; }
.pl-mg-room .bug { border-radius: var(--29d-r-3); box-shadow: var(--29d-shadow-pop); }
.pl-mg-room .mg .bug-bar {
    width: 100%; display: flex; align-items: center; gap: var(--29d-s-2);
    background: var(--mg-yellow); color: var(--mg-ink);
    border: none; border-radius: var(--29d-r-3); cursor: pointer;
    padding: var(--29d-s-2) var(--29d-s-3); min-height: 52px;
    font-family: var(--29d-font-display); text-align: left;
    transition: transform var(--29d-t-instant) var(--29d-ease);
  }
.pl-mg-room .bug-bar:active { transform: scale(.99); }
.pl-mg-room .bug-bar:focus-visible { outline: none; box-shadow: var(--29d-focus-halo); }
.pl-mg-room .bug[data-open="true"] .bug-bar { border-radius: var(--29d-r-3) var(--29d-r-3) 0 0; }
.pl-mg-room .bug-dot { width: 9px; height: 9px; border-radius: var(--29d-pill); background: var(--29d-red-600); flex: none; animation: bugpulse 1.6s infinite; }
@keyframes bugpulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
.pl-mg-room .bug-dot { animation: none; }
}
.pl-mg-room .bug-bar-left { display: flex; align-items: center; gap: var(--29d-s-2); min-width: 0; flex: 1; }
.pl-mg-room .bug-name { font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-md); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-transform: uppercase; letter-spacing: .02em; }
.pl-mg-room .bug-bar-mid { display: flex; align-items: baseline; gap: var(--29d-s-0); flex: none; }
.pl-mg-room .bug-score { font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-2xl); line-height: 1; }
.pl-mg-room .bug-score-of { font-weight: var(--29d-weight-bold); font-size: var(--29d-text-sm); opacity: .65; }
.pl-mg-room .bug-rank-label { font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-sm); margin-left: var(--29d-s-1); background: var(--mg-ink); color: var(--mg-yellow); border-radius: var(--29d-r-1); padding: var(--29d-s-0) var(--29d-s-1); }
.pl-mg-room .bug-rank-label:empty { display: none; }
.pl-mg-room .bug-status { font-family: var(--29d-font-mono); font-size: var(--29d-text-2xs); text-transform: uppercase; letter-spacing: .08em; opacity: .75; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 26%; }
.pl-mg-room .bug-caret { flex: none; display: flex; transition: transform var(--29d-t-base) var(--29d-ease); }
.pl-mg-room .bug[data-open="true"] .bug-caret { transform: rotate(180deg); }
.pl-mg-room .bug-panel { background: var(--29d-surface); border: 1px solid var(--29d-border); border-top: none; border-radius: 0 0 var(--29d-r-3) var(--29d-r-3); overflow: hidden; }
.pl-mg-room .bug-board-head { display: flex; align-items: center; gap: var(--29d-s-2); background: var(--mg-ink); color: var(--mg-yellow); padding: var(--29d-s-2) var(--29d-s-3); }
.pl-mg-room .bug-board-title { font-family: var(--29d-font-display); font-weight: var(--29d-weight-xbold); text-transform: uppercase; letter-spacing: .06em; font-size: var(--29d-text-md); }
.pl-mg-room .bug-board-live { display: flex; align-items: center; gap: var(--29d-s-1); font-family: var(--29d-font-mono); font-size: var(--29d-text-2xs); text-transform: uppercase; letter-spacing: .08em; }
.pl-mg-room .bug-board-live .bug-dot { background: var(--mg-yellow); }
.pl-mg-room .bug-board-updated { margin-left: auto; font-family: var(--29d-font-mono); font-size: var(--29d-text-2xs); opacity: .8; }
.pl-mg-room .bug-board-empty { padding: var(--29d-s-4) var(--29d-s-3); color: var(--29d-text-2); font-size: var(--29d-body-size); }
.pl-mg-room .bug-table { width: 100%; border-collapse: collapse; }
.pl-mg-room .bug-table th { font-family: var(--29d-font-mono); font-size: var(--29d-text-2xs); text-transform: uppercase; letter-spacing: .08em; color: var(--29d-text-3); font-weight: var(--29d-weight-semibold); text-align: right; padding: var(--29d-s-2) var(--29d-s-2); border-bottom: 1px solid var(--29d-border); }
.pl-mg-room .bug-table th.bug-th-name { text-align: left; }
.pl-mg-room .bug-table th.bug-th-total, .pl-mg-room .bug-table td.bug-total { padding-right: var(--29d-s-3); }
.pl-mg-room .bug-table th.bug-th-rank, .pl-mg-room .bug-table td.bug-rank { padding-left: var(--29d-s-3); text-align: left; }
.pl-mg-room .bug-table td { padding: var(--29d-s-2); border-bottom: 1px solid var(--29d-border); font-size: var(--29d-body-size); text-align: right; color: var(--29d-text-2); }
.pl-mg-room .bug-table tr:last-child td { border-bottom: none; }
.pl-mg-room .bug-table td.bug-rank { font-family: var(--29d-font-display); font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-lg); color: var(--29d-text-1); text-align: left; }
.pl-mg-room .bug-table td.bug-player { text-align: left; font-weight: var(--29d-weight-semibold); color: var(--29d-text-1); max-width: 130px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-mg-room .bug-table td.bug-total { font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-lg); color: var(--29d-text-1); }
.pl-mg-room .bug-table tr.is-mine td { background: var(--29d-amber-100); }
.pl-mg-room .bug-table tr.is-mine td.bug-rank { color: var(--29d-coral-700); }
.pl-mg-room .bug-foot { padding: var(--29d-s-2) var(--29d-s-3); font-size: var(--29d-text-xs); color: var(--29d-text-3); border-top: 1px solid var(--29d-border); }
@media (max-width: 430px) {
.pl-mg-room .bug-table th, .pl-mg-room .bug-table td { padding-left: var(--29d-s-1); padding-right: var(--29d-s-1); }
.pl-mg-room .bug-table th.bug-th-total, .pl-mg-room .bug-table td.bug-total { padding-right: var(--29d-s-2); }
.pl-mg-room .bug-table th.bug-th-rank, .pl-mg-room .bug-table td.bug-rank { padding-left: var(--29d-s-2); }
.pl-mg-room .bug-table td.bug-player { max-width: 104px; }
.pl-mg-room .bug-status { display: none; }
}
.pl-mg-room main { margin-top: var(--29d-s-4); }
.pl-mg-room .screen[hidden] { display: none; }
.pl-mg-room .hero { text-align: center; padding: var(--29d-s-6) var(--29d-s-2) var(--29d-s-4); }
.pl-mg-room .hero-eyebrow { font-family: var(--29d-font-mono); font-size: var(--29d-text-xs); text-transform: uppercase; letter-spacing: .14em; color: var(--29d-coral-700); font-weight: var(--29d-weight-semibold); }
.pl-mg-room .hero-title { font-family: var(--29d-font-display); font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-4xl); line-height: var(--29d-lh-4xl); margin-top: var(--29d-s-2); }
.pl-mg-room .hero-sub { color: var(--29d-text-2); font-size: var(--29d-text-lg); line-height: var(--29d-lh-lg); margin-top: var(--29d-s-2); }
.pl-mg-room .card { background: var(--29d-surface); border: 1px solid var(--29d-border); border-radius: var(--29d-r-3); padding: var(--29d-card-pad); }
.pl-mg-room .stack { display: grid; gap: var(--29d-s-3); }
.pl-mg-room .name-form { display: grid; gap: var(--29d-s-3); }
.pl-mg-room .name-input { font-size: var(--29d-text-lg); min-height: 56px; text-align: center; font-weight: var(--29d-weight-semibold); }
.pl-mg-room .big-btn { min-height: 56px; font-size: var(--29d-text-lg); font-weight: var(--29d-weight-bold); width: 100%; }
.pl-mg-room .fineprint { font-size: var(--29d-text-xs); color: var(--29d-text-3); text-align: center; line-height: var(--29d-lh-xs); }
.pl-mg-room .round-eyebrow { font-family: var(--29d-font-mono); font-size: var(--29d-text-xs); text-transform: uppercase; letter-spacing: .14em; color: var(--29d-coral-700); font-weight: var(--29d-weight-semibold); text-align: center; }
.pl-mg-room .round-title { font-family: var(--29d-font-display); font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-3xl); line-height: var(--29d-lh-3xl); text-align: center; margin-top: var(--29d-s-1); }
.pl-mg-room .round-how { text-align: center; color: var(--29d-text-2); font-size: var(--29d-text-lg); line-height: var(--29d-lh-lg); margin-top: var(--29d-s-2); }
.pl-mg-room .round-sofar { text-align: center; font-size: var(--29d-text-sm); color: var(--29d-text-3); }
.pl-mg-room .hud { display: flex; justify-content: space-between; align-items: baseline; gap: var(--29d-s-2); padding: 0 var(--29d-s-1) var(--29d-s-2); }
.pl-mg-room .hud-label { font-family: var(--29d-font-mono); font-size: var(--29d-text-2xs); text-transform: uppercase; letter-spacing: .1em; color: var(--29d-text-3); }
.pl-mg-room .hud-value { font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-xl); }
.pl-mg-room .hud-msg { text-align: center; min-height: var(--29d-lh-lg); font-size: var(--29d-text-lg); font-weight: var(--29d-weight-semibold); padding-top: var(--29d-s-2); }
.pl-mg-room .meter { height: 18px; border-radius: var(--29d-pill); background: var(--29d-sunken); border: 1px solid var(--29d-border); position: relative; overflow: hidden; margin-top: var(--29d-s-3); }
.pl-mg-room .meter-sweet { position: absolute; top: 0; bottom: 0; left: 50%; width: 10%; background: var(--29d-green-100); border-left: 1px solid var(--29d-green-600); border-right: 1px solid var(--29d-green-600); }
.pl-mg-room .meter-fill { position: absolute; top: 0; bottom: 0; left: 0; width: 0%; background: var(--29d-coral-600); }
.pl-mg-room .meter-label { display: flex; justify-content: space-between; font-family: var(--29d-font-mono); font-size: var(--29d-text-2xs); text-transform: uppercase; letter-spacing: .08em; color: var(--29d-text-3); margin-top: var(--29d-s-1); }
.pl-mg-room canvas#court { width: 100%; display: block; border-radius: var(--29d-r-3); border: 1px solid var(--29d-border); touch-action: none; background: var(--29d-teal-100); }
.pl-mg-room .pad { border-radius: var(--29d-r-3); border: 1px solid var(--29d-border); min-height: 264px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--29d-s-2); text-align: center; padding: var(--29d-s-4); cursor: pointer; user-select: none; -webkit-user-select: none; touch-action: manipulation; transition: background var(--29d-t-fast) var(--29d-ease); }
.pl-mg-room .pad-big { font-family: var(--29d-font-display); font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-3xl); line-height: var(--29d-lh-3xl); }
.pl-mg-room .pad-small { font-size: var(--29d-text-md); }
.pl-mg-room .pad.is-idle { background: var(--29d-sunken); color: var(--29d-text-2); }
.pl-mg-room .pad.is-wait { background: var(--29d-amber-100); color: var(--29d-amber-700); }
.pl-mg-room .pad.is-go { background: var(--29d-green-600); color: var(--29d-on-dark); }
.pl-mg-room .pad.is-early { background: var(--29d-red-100); color: var(--29d-red-700); }
.pl-mg-room .pad.is-done { background: var(--29d-sunken); color: var(--29d-text-1); }
.pl-mg-room .clock-face { font-weight: var(--29d-weight-xbold); font-size: 64px; line-height: 1.1; text-align: center; font-variant-numeric: tabular-nums; }
.pl-mg-room .clock-target { text-align: center; color: var(--29d-text-2); font-size: var(--29d-text-lg); }
.pl-mg-room .clock-bar { height: 12px; border-radius: var(--29d-pill); background: var(--29d-sunken); border: 1px solid var(--29d-border); overflow: hidden; }
.pl-mg-room .clock-bar-fill { height: 100%; width: 0%; background: var(--29d-gold-500); }
.pl-mg-room .arena { position: relative; height: 380px; border-radius: var(--29d-r-3); border: 1px solid var(--29d-border); overflow: hidden; background: var(--29d-teal-100); touch-action: manipulation; }
.pl-mg-room .arena-sand { position: absolute; left: 0; right: 0; bottom: 0; height: 30%; background: var(--29d-amber-100); border-top: 1px solid var(--29d-border-strong); }
.pl-mg-room .arena-sun { position: absolute; top: var(--29d-s-3); right: var(--29d-s-3); width: 46px; height: 46px; border-radius: var(--29d-pill); background: var(--mg-yellow); border: 2px solid var(--mg-yellow-deep); }
.pl-mg-room .target { position: absolute; width: 58px; height: 58px; margin: -29px 0 0 -29px; border-radius: var(--29d-pill); border: 2px solid var(--29d-border-strong); background: var(--29d-surface); display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; animation: targetpop var(--29d-t-slow) var(--29d-ease-pop); }
.pl-mg-room .target:active { transform: scale(.92); }
.pl-mg-room .target.is-decoy { background: var(--29d-sunken); border-style: dashed; }
.pl-mg-room .target.is-hit { opacity: 0; transform: scale(1.35); transition: opacity var(--29d-t-fast) var(--29d-ease), transform var(--29d-t-fast) var(--29d-ease); }
@keyframes targetpop { from { transform: scale(.4); } to { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
.pl-mg-room .target { animation: none; }
}
.pl-mg-room .frenzy-bar { height: 12px; border-radius: var(--29d-pill); background: var(--29d-sunken); border: 1px solid var(--29d-border); overflow: hidden; }
.pl-mg-room .frenzy-bar-fill { height: 100%; width: 100%; background: var(--29d-coral-600); }
.pl-mg-room .final-total { text-align: center; font-family: var(--29d-font-display); font-weight: var(--29d-weight-xbold); font-size: 76px; line-height: 1; }
.pl-mg-room .final-total-of { text-align: center; color: var(--29d-text-3); font-weight: var(--29d-weight-semibold); margin-top: var(--29d-s-1); }
.pl-mg-room .final-rank { margin: var(--29d-s-4) auto 0; max-width: 340px; background: var(--mg-yellow); color: var(--mg-ink); border-radius: var(--29d-r-2); text-align: center; font-family: var(--29d-font-display); font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-lg); padding: var(--29d-s-2) var(--29d-s-3); }
.pl-mg-room .breakdown { display: grid; }
.pl-mg-room .breakdown-row { display: flex; align-items: baseline; gap: var(--29d-s-2); padding: var(--29d-s-2) 0; border-bottom: 1px solid var(--29d-border); }
.pl-mg-room .breakdown-row:last-child { border-bottom: none; }
.pl-mg-room .breakdown-name { font-weight: var(--29d-weight-semibold); flex: 1; }
.pl-mg-room .breakdown-detail { color: var(--29d-text-3); font-size: var(--29d-text-sm); }
.pl-mg-room .breakdown-score { font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-xl); }
.pl-mg-room .post-status { text-align: center; font-size: var(--29d-text-sm); color: var(--29d-text-2); min-height: var(--29d-lh-sm); }
.pl-mg-room .foot { margin-top: var(--29d-s-8); display: flex; justify-content: space-between; align-items: center; }
.pl-mg-room .foot-brand { font-family: var(--29d-font-mono); font-size: var(--29d-text-2xs); text-transform: uppercase; letter-spacing: .1em; color: var(--29d-text-3); }
.pl-mg-room .theme-btn { background: none; border: 1px solid var(--29d-border); border-radius: var(--29d-r-2); color: var(--29d-text-2); font-size: var(--29d-text-xs); padding: var(--29d-s-1) var(--29d-s-2); cursor: pointer; min-height: 36px; }
.pl-mg-room .card-spaced { margin-top: var(--29d-s-3); }
.pl-mg-room .sponsor-card { background: var(--mg-ink); color: var(--mg-yellow); border-radius: var(--29d-r-3); padding: var(--29d-s-6) var(--29d-s-4); text-align: center; box-shadow: var(--29d-shadow-pop); }
.pl-mg-room .sponsor-eyebrow { font-family: var(--29d-font-mono); font-size: var(--29d-text-xs); text-transform: uppercase; letter-spacing: .14em; opacity: .85; }
.pl-mg-room .sponsor-title { font-family: var(--29d-font-display); font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-3xl); line-height: var(--29d-lh-3xl); margin-top: var(--29d-s-2); }
.pl-mg-room .sponsor-title-sm { font-size: var(--29d-text-2xl); line-height: var(--29d-lh-2xl); }
.pl-mg-room .sponsor-copy { font-size: var(--29d-text-lg); line-height: var(--29d-lh-lg); margin-top: var(--29d-s-2); color: var(--29d-on-dark); }
.pl-mg-room .sponsor-link { display: inline-flex; align-items: center; justify-content: center; margin-top: var(--29d-s-4); background: var(--mg-yellow); color: var(--mg-ink); font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-md); border-radius: var(--29d-r-2); padding: var(--29d-s-2) var(--29d-s-4); min-height: 48px; text-decoration: none; }
.pl-mg-room .sponsor-link:active { transform: scale(.98); }
.pl-mg-room .sponsor-mini { margin-top: var(--29d-s-4); padding: var(--29d-s-4); }
.pl-mg-room .heb-stage { background: var(--29d-surface); border: 1px solid var(--29d-border); border-radius: var(--29d-r-3); margin-top: var(--29d-s-3); }
.pl-mg-room .heb-glyph { font-family: "Times New Roman", "Noto Serif Hebrew", serif; font-size: 118px; line-height: 1.2; text-align: center; padding: var(--29d-s-3) 0; }
.pl-mg-room .heb-choices { display: grid; grid-template-columns: 1fr 1fr; gap: var(--29d-s-2); margin-top: var(--29d-s-3); }
.pl-mg-room .heb-choice { min-height: 64px; font-size: var(--29d-text-md); font-weight: var(--29d-weight-bold); white-space: normal; line-height: var(--29d-lh-md); background: var(--29d-surface); color: var(--29d-text-1); border-color: var(--29d-border-strong); }
.pl-mg-room .heb-choice:hover { background: var(--29d-wash); }
.pl-mg-room .heb-choice:active { transform: scale(.98); }
.pl-mg-room .heb-choice.is-right { background: var(--29d-green-100); border-color: var(--29d-green-600); color: var(--29d-green-700); }
.pl-mg-room .heb-choice.is-wrong { background: var(--29d-red-100); border-color: var(--29d-red-100); color: var(--29d-red-700); }
.pl-mg-room .arm-q { font-family: var(--29d-font-display); font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-2xl); line-height: var(--29d-lh-2xl); text-align: center; padding: var(--29d-s-5) var(--29d-s-3); color: var(--29d-text-1); }
.pl-mg-room .bonus-menu { display: grid; gap: var(--29d-s-2); }
.pl-mg-room .bonus-stats-list { display: grid; gap: var(--29d-s-2); }
.pl-mg-room .bonus-stat-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--29d-s-3); background: var(--29d-surface); border: 1px solid var(--29d-border); border-radius: var(--29d-r-2); padding: var(--29d-s-2) var(--29d-s-3); }
.pl-mg-room .bonus-stat-who { font-weight: var(--29d-weight-bold); color: var(--29d-text-1); }
.pl-mg-room .bonus-stat-what { color: var(--29d-text-2); font-size: var(--29d-text-sm); }
.pl-mg-room .bonus-stat-reps { font-family: var(--29d-font-mono); font-weight: var(--29d-weight-xbold); font-size: var(--29d-text-lg); color: var(--29d-text-1); }

.pl-mg-room #theme-btn { display: none; }

.pl-mg-room { display: block; }

/* ==== MIDDAY GAME MGFX IN-SHELL (§71c, 2026-10-24 — UI-21) ====
   The In-Shell Law (the Principal's ruling, 2026-10-24 08:22 PT),
   applied to the Midday Game's reaction layer (census E-02/X-04).
   mgfx.js appends its canvas, success scene, wash and edge glow to
   document.body as position:fixed; inset:0 layers, and drops its
   ring/flash receipts as fixed spawns — in-room, the game's weather
   used to take the whole window and bury the shell. The §71c block
   in app.js re-homes every one of those nodes into .pl-mg-room;
   the rules below bound them absolute-in-room. The room becomes a
   stacking context (position:relative + z-index:0 + isolation), so
   the layers' own z-order (canvas 35, wash/glow 57, scene 58, the
   scene-on canvas raise to 62) orders them INSIDE the room exactly
   as the module intends and can never climb over the shell's head,
   shelf or player. The module's paint is not re-dressed: the scene
   IS the game's sunny moment — the shell changes where it lives,
   not what it says, so no tokens are spent here at all (the §71b
   token discipline is honoured trivially). The canvas bitmap is
   the module's own viewport-sized surface; width/height need
   !important because the module sizes the element inline
   (style.width/height in px) on build and on resize. Pointer-events
   stay the module's own none throughout: weather you watch, never
   a wall you fight. The game's bytes (mgfx.js / mgfx.css and the
   rest of /midday-game/) are untouched. */
.pl-mg-room { position: relative; z-index: 0; isolation: isolate; }
#plPlace .pl-mg-room #mgfx-canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
#plPlace .pl-mg-room #mgfx-scene { position: absolute; inset: 0; }
#plPlace .pl-mg-room #mgfx-wash { position: absolute; inset: 0; }
#plPlace .pl-mg-room #mgfx-edgeglow { position: absolute; inset: 0; }
#plPlace .pl-mg-room .mgfx-ring { position: absolute; }
#plPlace .pl-mg-room .mgfx-flash { position: absolute; }
/* ==== /MIDDAY GAME MGFX IN-SHELL (§71c) ==== */

/* ==== SHELF PLACEMENT (§61) — the toolbar's three homes ====
   Bottom is the canon dress (tide.css) and needs no rule here.
   TOP: the shelf takes the first flex slot of the stage; its
   bottom margin becomes the gap below it, and the scroller's
   reserve moves to the top edge. SIDE: the stage becomes a row —
   the rail takes the first slot at the left edge, 64px wide, a
   vertical stack of orbs only: brand and spacer fold away, the
   clock folds to its time (date + weather line rest), and the
   content column clears the rail's slot. Rooms, sheets and the
   player respect the same slot in every placement (§62). */
.pl-stage.pl-shelf-top .pl-shelf { order: -1; margin: var(--safe-t) auto 10px; }
.pl-stage.pl-shelf-top.pl-compact .pl-shelf { margin-top: var(--safe-t); margin-bottom: 10px; }
.pl-stage.pl-shelf-top.pl-touch .pl-main { scroll-padding-bottom: 12px;
  scroll-padding-top: calc(var(--pl-shelf-reserve, 0px) + 12px); }
.pl-stage.pl-shelf-side { flex-direction: row; }
.pl-stage.pl-shelf-side .pl-main { flex: 1 1 auto; min-width: 0; }
.pl-stage.pl-shelf-side .pl-shelf { flex-direction: column; justify-content: flex-start;
  order: -1; width: 64px; height: auto; align-self: stretch; flex: none;
  margin: calc(10px + var(--safe-t)) 0 calc(10px + var(--safe-b)) calc(10px + env(safe-area-inset-left, 0px));
  padding: 12px 0; gap: 10px; border-radius: 28px; }
.pl-stage.pl-shelf-side .pl-shelf .pl-orb { width: 44px; height: 44px; }
.pl-stage.pl-shelf-side .pl-shelf-brand, .pl-stage.pl-shelf-side .pl-shelf .pl-spacer { display: none; }
.pl-stage.pl-shelf-side .pl-clock-center { position: static; transform: none; pointer-events: none; }
.pl-stage.pl-shelf-side .pl-clock-center .pl-clock-date,
.pl-stage.pl-shelf-side .pl-clock-sub { display: none; }
.pl-stage.pl-shelf-side .pl-clock-center { width: 100%; }
.pl-stage.pl-shelf-side .pl-clock-center .pl-clock-time { font-size: 12.5px; letter-spacing: -.03em; white-space: nowrap; }
.pl-stage.pl-shelf-side .pl-clock-center .pl-clock-time small { display: none; }
.pl-stage.pl-shelf-side.pl-touch .pl-main { scroll-padding-bottom: 12px; }

/* ==== ROOM SLOT (§62) — rooms stop at the shelf's slot ====
   The rooms used to reserve a hardcoded 88px band at the bottom
   and hope the shelf fit inside it; on Michael's page it did not
   — the Listen room's sheet ran down over the dock and buried
   the clock (Victor's 11:46 screenshot, 2026-10-23). The band is
   now the MEASURED slot (§60/§61 publish --pl-shelf-reserve), it
   follows the placement, and while the player is up it grows by
   the player's own reserved band, so exactly one bar ever shows
   and no room ever covers it. */
.pl-stage .pl-sheet, .pl-stage .pl-folder, .pl-stage .pl-search {
  bottom: calc(var(--pl-shelf-reserve, 88px) + var(--pl-shelf-lift, 0px)); }
.pl-stage.pl-playing .pl-sheet, .pl-stage.pl-playing .pl-folder {
  bottom: calc(var(--pl-shelf-reserve, 88px) + var(--pl-shelf-lift, 0px) + 88px); }
.pl-player { bottom: calc(var(--pl-shelf-reserve, 86px) + var(--pl-shelf-lift, 0px) + 2px); }
.pl-stage.pl-shelf-top .pl-sheet, .pl-stage.pl-shelf-top .pl-folder, .pl-stage.pl-shelf-top .pl-search {
  top: calc(var(--pl-shelf-reserve, 88px) + var(--safe-t)); bottom: 0; }
.pl-stage.pl-shelf-top.pl-playing .pl-sheet, .pl-stage.pl-shelf-top.pl-playing .pl-folder { bottom: 88px; }
.pl-stage.pl-shelf-top .pl-player { bottom: calc(16px + var(--safe-b)); }
.pl-stage.pl-shelf-side .pl-sheet, .pl-stage.pl-shelf-side .pl-folder, .pl-stage.pl-shelf-side .pl-search {
  left: calc(var(--pl-shelf-reserve, 74px) + env(safe-area-inset-left, 0px)); bottom: 0; }
.pl-stage.pl-shelf-side.pl-playing .pl-sheet, .pl-stage.pl-shelf-side.pl-playing .pl-folder { bottom: 88px; }
.pl-stage.pl-shelf-side .pl-player { left: calc(var(--pl-shelf-reserve, 74px) + env(safe-area-inset-left, 0px) + 18px);
  right: 8px; width: auto; transform: none; bottom: calc(16px + var(--safe-b)); }
.pl-stage.pl-touch.pl-shelf-top .pl-tour, .pl-stage.pl-touch.pl-shelf-side .pl-tour {
  padding-bottom: calc(16px + var(--safe-b)); }

/* ==== DUO / FOLDABLE FORM FACTORS (§69, 2026-10-23 — Danny Peyton
   via Victor: "when is my portal gonna be updated for iPhone duo
   support? Need to get that nav bar blended and make that
   persistent banner at the bottom with the time disappear on
   scroll.") ====
   The WIDE band — 600–1180px viewport width, the unfolded-
   foldable class (Fold inner ~690 portrait / ~830 landscape,
   Duo screens ~540–1080) below the desktop measure — gets three
   things, and the app.js §69 block is the third's driver:
   (1) FORM: the touch posture now REACHES foldables (app.js
       compactCheck §69 — the old gate's min-dimension ≤480 test
       exiled every unfolded foldable to the mouse pager). In the
       band the home stops wearing the phone's 2-across stretch:
       squares run 3-across (600–759) and 4-across (760+) at the
       desktop tile aspect, and the home column's cards (the §64
       BMS card, the Ad of the Day) pair side by side — two
       zones, designed, not a centred column in dead sky.
   (2) BLEND: Danny's "nav bar blended" — in the band, the
       shelf's banner dress (bar fill, edge line, shadow, blur)
       stands down and the orbs + clock float on the page's own
       sky. Narrow and desktop dresses are untouched, and the
       §61 placements keep working: at SIDE the rail instead
       GROWS into the full rail (brand + whole clock return;
       §62's measured reserve follows the wider slot on its own).
   (3) HIDE-ON-SCROLL: the banner (bottom or top placement)
       slides away on scroll down, returns on scroll up / at
       top (driver: app.js §69; state: .pl-shelf-hidden). The
       SIDE stash never hides — it is a rail, not a banner.
   INVARIANTS, by construction (Overlap Gate + §62 + §68): the
   hide is TRANSFORM-ONLY — the shelf keeps its layout slot, so
   --pl-shelf-reserve / --pl-shelf-lift / the §60 scroll-padding
   are identical in both states: nothing jumps when it hides,
   no content is ever trapped under the returning bar, and the
   §68 toast dock (which reads placement + the player's rect
   only) never sees the hidden state at all. The PLAYER is a
   separate bar anchored to the reserved slot (§62): it does
   not move, does not hide, and stays the ONE visible bar in
   every state — hiding chrome never stops or strands playback. */
/* (3) the banner's two states — every width, bottom + top */
.pl-shelf { transition: transform .3s var(--ease), opacity .3s var(--ease); }
.pl-stage.pl-shelf-hidden:not(.pl-shelf-top):not(.pl-shelf-side) .pl-shelf {
  transform: translateY(calc(100% + 20px)); opacity: 0; pointer-events: none; }
.pl-stage.pl-shelf-top.pl-shelf-hidden .pl-shelf {
  transform: translateY(calc(-100% - 20px)); opacity: 0; pointer-events: none; }
html[data-motion="reduced"] .pl-shelf { transition: none; }

@media (min-width: 600px) and (max-width: 1180px) {
  /* (2) BLEND — the bottom/top banners lose the seam */
  .pl-stage:not(.pl-shelf-side) .pl-shelf { background: transparent; border-color: transparent;
    box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
  /* (2b) the side stash at wide is the full rail */
  .pl-stage.pl-shelf-side .pl-shelf { width: 168px; border-radius: 32px; padding: 16px 0; gap: 12px; }
  .pl-stage.pl-shelf-side .pl-shelf-brand { display: block; }
  .pl-stage.pl-shelf-side .pl-shelf .pl-spacer { display: block; }
  .pl-stage.pl-shelf-side .pl-clock-center .pl-clock-time { font-size: 19px; letter-spacing: -.01em; }
  .pl-stage.pl-shelf-side .pl-clock-center .pl-clock-time small { display: inline; }
  .pl-stage.pl-shelf-side .pl-clock-center .pl-clock-date,
  .pl-stage.pl-shelf-side .pl-clock-center .pl-clock-sub { display: block; }
  /* (1) FORM — the touch home in the wide band. Banner placements
     only: at SIDE the rail already zones the stage, and the home
     column keeps its single-column flow (rig finding, 2026-10-23:
     row-wrapping the column beside the rail squeezed the lad
     pages' first-run strips into vertical ribbons). */
  .pl-stage.pl-touch:not(.pl-shelf-side) .pl-main { flex-direction: row; flex-wrap: wrap;
    align-content: flex-start; align-items: stretch; column-gap: 10px; }
  .pl-stage.pl-touch:not(.pl-shelf-side) .pl-favbar, .pl-stage.pl-touch:not(.pl-shelf-side) .pl-filter-banner { flex: 1 1 100%; }
  .pl-stage.pl-touch:not(.pl-shelf-side) .pl-bms, .pl-stage.pl-touch:not(.pl-shelf-side) .pl-adotd { flex: 1 1 330px; width: auto; margin: 0 0 10px; }
  .pl-stage.pl-touch:not(.pl-shelf-side) .pl-pages-clip { flex: 1 1 100%; }
  .pl-stage.pl-touch:not(.pl-shelf-side) .pl-page { grid-template-columns: repeat(3, 1fr); }
  .pl-stage.pl-touch:not(.pl-shelf-side) .pl-tile { aspect-ratio: 1.72; }
}
@media (min-width: 760px) and (max-width: 1180px) {
  .pl-stage.pl-touch:not(.pl-shelf-side) .pl-page { grid-template-columns: repeat(4, 1fr); }
}
/* folded cover screens (≤380): the $8 card's foot wraps before it clips */
@media (max-width: 380px) {
  .pl-bms { padding: 16px 14px 14px; }
  .pl-bms-foot { flex-wrap: wrap; }
}
/* ==== /DUO (§69) ==== */


/* ==== MYSTERY PRESENT (§70, win-back pass, 2026-10-23) ====
   The Bot Manners offer no longer stands on a lad's home as the
   §64 sales card (the .pl-bms rules above are retired with it —
   the publisher emits no card; they stay only because the
   canonical entry's stylesheet is shared). The offer rides as a
   wrapped present, the last of his own tiles; §70 in app.js gives
   the tile its wrap-it-back-up corner ✕ (the .pl-tile-plus corner
   grammar: 30px, top-right, a sibling of the tile face) and hides
   the tile under a stage class when he has put it away — a class,
   not node surgery, because the grid rebuilds its tiles and the
   put-away state must survive every rebuild. */
.pl-gift-x { position: absolute; z-index: 6; top: 8px; right: 8px;
  width: 40px; height: 40px; border-radius: 50%; padding: 0; /* P4 (night loop 2026-10-24): rides the .pl-tile-plus corner grammar, which moved 30px → 40px this round (the shell's tap floor); the §70 note above records the grammar at its old size. */
  border: 1px solid var(--pl-tile-rim, rgba(0,0,0,.15));
  background: var(--pl-orb-face, #FFFDF8); color: var(--pl-tile-ink, inherit);
  font-size: 14px; line-height: 1; display: flex; align-items: center;
  justify-content: center; cursor: pointer;
  box-shadow: 0 2px 6px rgba(0,0,0,.18); -webkit-tap-highlight-color: transparent; }
.pl-gift-x:hover { transform: scale(1.08); }
.pl-gift-x:active { transform: scale(.94); }
.pl-gift-x:focus-visible { outline: 3px solid var(--pl-focus, #2b7de9); outline-offset: 2px; }
.pl-stage.pl-gift-away c29-channel[data-square$="-gift"] { display: none; }
/* ==== /MYSTERY PRESENT (§70) ==== */

/* ==== CHUGBOT (§71, 2026-10-23; §71b IN-SHELL, 2026-10-24) ====
   The restored module wears the room's own tokens: its in-room card
   reads as a Pleasant card — his tile face and rim, his ink — in
   light or dark, skin or house, because the shell's --pl-* vars
   already carry all of that.
   §71b (UI-19 — the Principal's In-Shell Law, 2026-10-24 08:22 PT:
   "if you launch something in pleasant, it stays in fucking
   pleasant. Without these horrible windows shit... it needs to be
   great on mobile"): §71's original note — the module's overlay
   "stays its own dark camera UI in every theme" — is SUPERSEDED.
   The module appends its coach overlay + confetti canvas to
   document.body as viewport-fixed layers; the §71 loader re-homes
   both into the room body, and the rules below bound the overlay as
   an in-flow citizen of the room (the room's own scroll carries it,
   under the room's sticky head) and re-dress its chrome, light +
   dark, while the resting card yields (.pl-cb-live). The module's
   overlay colors are literals (its --29d-* vars serve only the
   card), so each is overridden head-on. TOKEN DISCIPLINE: only
   tokens BOTH registers define are used — the action color is
   --pl-badge/--pl-on-badge (the house coral family the bot itself
   wears), secondary buttons mirror .pl-note-btn (tile face +
   --edge-soft hairline + tile ink). --pl-accent and --pl-line are
   pleasant-tide-REGISTER tokens, undefined in the default register
   — a first cut used them and the primary buttons silently lost
   their fill (invalid at computed-value time); the rig now probes
   the resolved tokens so the class cannot regress quietly. The
   camera STAGE stays the module's dark framed port — it is a
   screen: the viewfinder well, the pill and the verdict ride on
   the picture in every theme. The module's bytes (the brain) are
   untouched; only its presentation is re-homed. */
#chugbot-mount { --29d-surface: var(--pl-tile-face); --29d-border: var(--pl-tile-rim); --29d-text-1: var(--pl-ink); }
#chugbot-mount .cb-card { box-shadow: var(--pl-tile-shadow); color: var(--pl-ink); }
#plPlace .cb-overlay { position: relative; inset: auto; z-index: auto;
  width: 100%; max-width: none; height: auto; max-height: none;
  margin: 0; padding: 4px 0 8px; overflow: visible; border: 0;
  background: transparent; color: var(--pl-ink); font-family: inherit; }
#plPlace .cb-overlay.open { display: flex; }
@media (min-width: 640px) {
  #plPlace .cb-overlay { width: 100%; max-width: none; margin: 0; max-height: none; } }
#plPlace .cb-confetti { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 5; }
.pl-cb-live > #chugbot-mount { display: none; }
#plPlace .cb-overlay .cb-close, #plPlace .cb-overlay .cb-arm,
#plPlace .cb-overlay .cb-mode { border-color: var(--edge-soft, var(--pl-tile-rim)); color: var(--pl-tile-ink); background: var(--pl-tile-face); }
#plPlace .cb-overlay .cb-mode[aria-pressed="true"] { background: var(--pl-badge); border-color: var(--pl-badge); color: var(--pl-on-badge); }
#plPlace .cb-overlay .cb-bigbtn { background: var(--pl-badge); color: var(--pl-on-badge); }
#plPlace .cb-overlay .cb-bigbtn.stop { background: var(--pl-tile-ink); color: var(--pl-tile-face); }
#plPlace .cb-overlay .cb-bigbtn.is-quiet { background: transparent; border-color: var(--edge-soft, var(--pl-tile-rim)); color: var(--pl-tile-ink); }
#plPlace .cb-overlay .cb-arm.is-primary { background: var(--pl-badge); border-color: var(--pl-badge); color: var(--pl-on-badge); }
#plPlace .cb-overlay .cb-recal { background: transparent; color: var(--pl-ink-soft); }
#plPlace .cb-overlay .cb-dock { background: transparent; border-top-color: var(--edge-soft, var(--pl-tile-rim)); }
#plPlace .cb-overlay .cb-hof { border-top-color: var(--edge-soft, var(--pl-tile-rim)); }
#plPlace .cb-overlay .cb-hof li { border-bottom-color: var(--edge-soft, var(--pl-tile-rim)); }
#plPlace .cb-overlay .cb-camhelp { background: var(--pl-tile-face); border-color: var(--edge-soft, var(--pl-tile-rim)); color: var(--pl-ink); }
#plPlace .cb-overlay .cb-camhelp .cb-retry { border-color: var(--pl-badge); color: var(--pl-badge); }
#plPlace .cb-overlay .cb-paybtn { background: var(--pl-badge); color: var(--pl-on-badge); }
#plPlace .cb-overlay .cb-paybtn.soon { background: transparent; border-color: var(--edge-soft, var(--pl-tile-rim)); color: var(--pl-ink-soft); }
#plPlace .cb-overlay .cb-close:focus-visible, #plPlace .cb-overlay .cb-mode:focus-visible,
#plPlace .cb-overlay .cb-arm:focus-visible, #plPlace .cb-overlay .cb-bigbtn:focus-visible,
#plPlace .cb-overlay .cb-retry:focus-visible { outline-color: var(--pl-focus); }
/* ==== /CHUGBOT (§71) ==== */
/* ==== §82 DESK-MODULE GRAMMAR (2026-10-24, Priority-2 Fleet G):
   the {form}/{list}/{journal}/{bank}/{counter}/{composer}/
   {computed}/{planner}/{calendar}/{chart} family in the §71–§80
   shell vocabulary — labelled fields on skin tokens, 44px tap
   floors, hairline rows, the pick panel and check rows reused
   outright. All on skin tokens, light + dark. Inert on every
   surface that declares no §82 data. ==== */
.pl-gram-field { display: block; margin-top: 10px; }
.pl-gram-flabel { display: block; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--pl-tile-ink-soft); margin-bottom: 5px; }
.pl-gram-in { display: block; width: 100%; box-sizing: border-box; min-height: 44px; font: inherit; font-size: 16px; border-radius: 10px; border: 1px solid var(--edge-soft); padding: 8px 10px; background: var(--pl-tile-face); color: var(--pl-tile-ink); }
.pl-gram-ta { line-height: 1.5; }
.pl-gram-note { font-size: 13px; line-height: 1.5; color: var(--pl-tile-ink-soft); margin-top: 8px; }
.pl-gram-prompt { font-size: 15px; line-height: 1.5; font-weight: 700; color: var(--pl-tile-ink); margin-top: 6px; }
.pl-gram-list { margin-top: 8px; }
.pl-gram-row { display: flex; gap: 8px; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--edge-soft); }
.pl-gram-row:last-child { border-bottom: 0; }
.pl-gram-rowmain { flex: 1 1 auto; min-width: 0; }
.pl-gram-rowt { font-size: 14.5px; line-height: 1.4; font-weight: 600; color: var(--pl-tile-ink); overflow-wrap: break-word; }
.pl-gram-rowd { font-size: 13px; line-height: 1.4; color: var(--pl-tile-ink-soft); overflow-wrap: break-word; }
.pl-gram-mini { flex: none; min-height: 44px; min-width: 44px; padding: 6px 10px; border-radius: 999px; border: 1px solid var(--edge-soft); background: transparent; color: var(--pl-tile-ink); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
.pl-gram-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; margin-top: 10px; }
.pl-gram-add .pl-gram-in { flex: 1 1 120px; width: auto; }
.pl-gram-filters { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.pl-gram-chip { min-height: 40px; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--edge-soft); background: transparent; color: var(--pl-tile-ink-soft); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
.pl-gram-chip.is-on { background: var(--pl-badge); border-color: var(--pl-badge); color: var(--pl-on-badge); }
.pl-gram-bankt { font-size: 19px; font-weight: 800; line-height: 1.25; color: var(--pl-tile-ink); margin-top: 4px; overflow-wrap: break-word; }
.pl-gram-count { font-size: 24px; font-weight: 800; line-height: 1.25; color: var(--pl-tile-ink); margin-top: 10px; }
.pl-gram-dated { flex: none; font-size: 12px; color: var(--pl-tile-ink-soft); font-variant-numeric: tabular-nums; }
.pl-gram-compose { font-size: 15px; line-height: 1.55; color: var(--pl-tile-ink); margin-top: 8px; overflow-wrap: break-word; }
.pl-gram-bands { margin-top: 6px; }
.pl-gram-band { display: flex; gap: 12px; align-items: baseline; padding: 9px 0; border-bottom: 1px solid var(--edge-soft); }
.pl-gram-band:last-child { border-bottom: 0; }
.pl-gram-bandl { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 600; color: var(--pl-tile-ink-soft); overflow-wrap: break-word; }
.pl-gram-bandv { flex: none; font-size: 16px; font-weight: 800; color: var(--pl-tile-ink); font-variant-numeric: tabular-nums; }
.pl-gram-days { display: block; }
.pl-gram-day { padding: 10px 0; border-bottom: 1px solid var(--edge-soft); }
.pl-gram-day:last-child { border-bottom: 0; }
.pl-gram-dayh { font-size: 13px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--pl-tile-ink); }
.pl-gram-cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; margin-top: 10px; }
.pl-gram-calh { font-size: 11px; font-weight: 800; text-align: center; color: var(--pl-tile-ink-soft); padding: 4px 0; }
.pl-gram-cald { min-height: 44px; border: 1px solid var(--edge-soft); border-radius: 8px; padding: 4px; box-sizing: border-box; overflow: hidden; }
.pl-gram-cald.is-empty { border-color: transparent; }
.pl-gram-cald.is-today { border-color: var(--pl-badge); }
.pl-gram-cald.has-ev { background: color-mix(in srgb, var(--pl-badge) 10%, var(--pl-tile-face)); }
.pl-gram-caln { display: block; font-size: 12px; font-weight: 700; color: var(--pl-tile-ink); }
.pl-gram-calev { display: block; font-size: 10px; line-height: 1.3; color: var(--pl-tile-ink); overflow-wrap: break-word; }
.pl-gram-chart { margin-top: 8px; }
.pl-gram-bar { display: flex; gap: 10px; align-items: center; padding: 6px 0; }
.pl-gram-barl { flex: none; width: 96px; font-size: 13px; font-weight: 600; color: var(--pl-tile-ink-soft); overflow-wrap: break-word; }
.pl-gram-bartrack { flex: 1 1 auto; min-width: 0; height: 14px; border-radius: 999px; background: color-mix(in srgb, var(--pl-tile-ink) 10%, var(--pl-tile-face)); overflow: hidden; }
.pl-gram-barfill { display: block; height: 100%; background: var(--pl-badge); border-radius: 999px; }
.pl-gram-barv { flex: none; font-size: 14px; font-weight: 800; color: var(--pl-tile-ink); font-variant-numeric: tabular-nums; }
/* ==== /§82 DESK-MODULE GRAMMAR ==== */
/* §82b additions (GQ rulings): list footers/flags, planner standing */
.pl-gram-foot { margin-top: 4px; }
.pl-gram-flag { display: inline-block; margin-left: 8px; padding: 2px 8px; border-radius: 999px; background: var(--pl-badge); color: var(--pl-on-badge); font-size: 11px; font-weight: 800; letter-spacing: .04em; vertical-align: middle; }
.pl-gram-rep { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; font-size: 13.5px; font-weight: 600; color: var(--pl-tile-ink); }
.pl-gram-rep input { width: 20px; height: 20px; }

/* ================= LISTEN EPISODE VIEW (FLEET 4, 2026-10-25) =================
 * The Spotify episode-page hierarchy in Pleasant skin. Rows: the art is
 * the play button itself (no UI overlaid on the artwork); the row body
 * opens the episode view. Hero text sits on the token wash, never on
 * the art. Pre-canon staging: Fleet 3's canon components supersede
 * these classes when they land. */
.pl-ep-wrap { display: flex; gap: 8px; align-items: stretch; margin-bottom: 8px; }
/* F3 PERF R1 (2026-10-25, pleasant-performance): episode rows off-screen
   skip layout + paint; intrinsic size remembers real height after first
   render (116px = the measured row height, corrected in R4). */
.pl-ep-wrap { content-visibility: auto; contain-intrinsic-size: auto 116px; }
.pl-ep-wrap .pl-ep { margin-bottom: 0; flex: 1; min-width: 0; }
.pl-ep-wrap .pl-ep .tx { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.pl-ep-wrap .pl-ep .t { flex: none; }
.pl-ep-wrap .pl-ep .d { font-size: 12.5px; font-weight: 500; color: var(--pl-tile-ink-soft); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.pl-ep-art { flex: 0 0 auto; width: 56px; min-height: 56px; border-radius: 12px; border: 1px solid var(--edge-soft);
  background: var(--pl-sky-wash); color: var(--pl-ink); cursor: pointer; padding: 0; overflow: hidden; position: relative;
  display: flex; align-items: center; justify-content: center; font: inherit; }
.pl-ep-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.pl-ep-art .pl-ep-art-ic { font-size: 17px; font-weight: 800; display: none; }
.pl-ep-art.no-art .pl-ep-art-ic { display: block; }
.pl-epx-hero { background: color-mix(in srgb, var(--pl-sky-wash) 55%, transparent); border: 1px solid var(--edge-soft);
  border-radius: 16px; padding: 18px 16px 16px; margin-bottom: 12px; }
.pl-epx-art { width: min(232px, 62vw); aspect-ratio: 1; border-radius: 14px; overflow: hidden; position: relative;
  border: 1px solid var(--edge-soft); background: var(--pl-sky-wash); margin-bottom: 14px;
  display: flex; align-items: center; justify-content: center; }
.pl-epx-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.pl-epx-art .pl-epx-art-word { font-family: var(--pl-skin-font-display); font-weight: 800; font-size: 20px; color: var(--pl-ink); display: none; }
.pl-epx-art.no-art .pl-epx-art-word { display: block; }
.pl-epx-eyebrow { font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--pl-ink-soft); margin-bottom: 4px; }
.pl-epx-title { font-family: var(--pl-skin-font-display); font-size: 24px; font-weight: 800; line-height: 1.2; color: var(--pl-ink); margin: 0 0 6px; overflow-wrap: anywhere; }
.pl-epx-show { font-size: 15px; font-weight: 700; color: var(--pl-ink); }
.pl-epx-meta { font-size: 13px; font-weight: 600; color: var(--pl-ink-soft); margin-top: 2px; }
.pl-epx-np { font-size: 12.5px; font-weight: 700; color: var(--pl-ink); margin-top: 8px; }
.pl-epx-acts { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 4px 0 12px; }
.pl-epx-play { flex: 0 0 auto; width: 64px; height: 64px; border-radius: 50%; border: 0; cursor: pointer;
  background: #AF3718; color: #FFF; box-shadow: 0 10px 24px rgba(175,55,24,.35);
  display: flex; align-items: center; justify-content: center; font: inherit; }
.pl-epx-play:active { transform: scale(.96); }
.pl-epx-play-ic { font-size: 23px; font-weight: 800; line-height: 1; }
.pl-epx-quiet { font-size: 13.5px; font-weight: 700; color: var(--pl-ink); text-decoration: none; cursor: pointer;
  border: 1px solid var(--edge-soft); border-radius: 16px; padding: 12px 16px;
  background: color-mix(in srgb, var(--pl-tile-face) 94%, transparent);
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  width: 100%; box-sizing: border-box; margin-bottom: 8px; }
/* the quiet action stacks: label on its own line, the canonical
   Opens-outside chip under it — the label never wraps. */
.pl-epx-desc-t { font-size: 14.5px; line-height: 1.6; color: var(--pl-ink); margin: 0 0 8px; overflow-wrap: anywhere; }
.pl-epx-desc.clamped .pl-epx-desc-t { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.pl-epx-tags { font-size: 12px; font-weight: 600; color: var(--pl-ink-soft); margin: 2px 0 12px; }
