/* app.css — E.V.O.S. v1. Brand-faithful (evolv-brand skill + tokens.css).
 * Base + login mirror the current build so the opening page looks identical.
 * New components: topbar, pipeline board, sell-through table. */

/* ===================== base ===================== */
html{font-size:15px}
/* SMOOTH SCROLLING AND THE CI CURSOR (2026-09-03, user). Both are declared here rather than in a
   component: they are the chrome of the whole product.
   `scroll-behavior` is on `html` because that is the scrolling element, and it is switched off
   under reduced motion at the foot of this file with every other transition. */
html{scroll-behavior:smooth}
body{
  margin:0;background:var(--black);color:var(--grey);
  font-family:var(--font-body);font-weight:400;line-height:1.62;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;position:relative;min-height:100vh;
}
*{box-sizing:border-box}
img,svg{display:block;max-width:100%}
button{font-family:inherit}
h1,h2,h3{font-family:var(--font-display);color:#fff;font-weight:700;letter-spacing:.01em;margin:0}
::selection{background:rgba(255,255,255,.28);color:#fff}
.hidden{display:none!important}
.spacer{flex:1}
.muted{color:var(--grey-45)}
/* THE PAGE DECLARES ITS SCHEME (2026-09-29, from the Windows videos: a select's dropdown list drawn
   white with white words, a light scrollbar inside it). Chromium and Edge draw every native piece
   (dropdown lists, scrollbars, the date and file pickers, an unstyled input) in the page's declared
   colour scheme, and this page never declared one, so Windows painted them light; a Mac hides its
   scrollbars and draws the list itself, which is why nobody saw it there. Dark, on the root, and
   light again for print so the paper pages are unaffected. */
html{color-scheme:dark}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-track{background:transparent}
*::-webkit-scrollbar-thumb{background:var(--line-14);border-radius:8px;border:2px solid var(--black)}
*::-webkit-scrollbar-thumb:hover{background:var(--line-22)}

/* ===================== ambient background ===================== */
.bg{position:fixed;inset:0;z-index:-3;background:var(--black);overflow:hidden;pointer-events:none}
/* The three ambient glows are STATIC (2026-08-13, user): they were each drifting on a forever
   loop over a 52-74vw element, which is continuous full-screen compositing on every page for a
   movement almost nobody notices. The gradients stay, so the depth is unchanged. A deliberate
   E.V.O.S. deviation from the brand skill, which asks for slowly drifting glows. */
/* ONE AXIS GOVERNS THE WHOLE COMPOSITION (2026-08-31, user: "why does it feel like my screen goes
   darker when the lpt goes fullscreen"). It did, and it was these three rules: the glows were SIZED
   in vw and POSITIONED in vh. Full screen makes the viewport taller without making it wider, so
   they kept their size while their offsets pushed them further off the top and the bottom of a page
   that had just grown — g1 fell from covering 87% of the height to 74%, g3 from 94% to 78%, and the
   two bright centres spread apart towards the edges, taking the light off the middle of the page
   where the content is.
   THE OFFSETS ARE vw NOW, so the ambient layer cannot change shape when only the other axis moves.
   Converted at the proportion they were tuned at, a browser window about 0.57 as tall as it is wide:
   18vh -> 10.2vw, 6vh -> 3.4vw, 36vh -> 20.5vw. Identical to look at today, invariant from here on.
   The deck's own wash was always right, `inset:-20%` of its own box, which is why presenting never
   had this. */
.glow{position:absolute;border-radius:50%;filter:blur(70px)}
.glow.g1{width:60vw;height:60vw;left:-16vw;top:-10.2vw;background:radial-gradient(circle at 50% 50%,var(--depth-92),var(--depth-40) 36%,transparent 66%)}
.glow.g2{width:52vw;height:52vw;right:-14vw;top:3.4vw;background:radial-gradient(circle at 50% 50%,var(--depth-65),transparent 62%)}
.glow.g3{width:74vw;height:74vw;left:8vw;bottom:-20.5vw;background:radial-gradient(circle at 50% 50%,var(--depth-65),var(--depth-22) 38%,transparent 64%)}
.led{position:absolute;inset:0;opacity:.5;background-image:repeating-linear-gradient(0deg,rgba(255,255,255,.016) 0 1px,transparent 1px 3px),repeating-linear-gradient(90deg,rgba(255,255,255,.016) 0 1px,transparent 1px 3px)}
/* THE GROUND IS DITHERED, SO THE GLOWS DO NOT BAND (2026-09-29, user: "check the dithering for
   the bg so there are no gradient bands"). Depth Navy at under half strength spreads about 38
   blue levels over half a screen, so an 8-bit screen holds one value for 22px on average and up
   to 252px: those runs are the bands. A fixed noise tile blended OVERLAY breaks them (measured:
   about 3px, longest 45px). Two details carry it, both measured in headless Chrome against the
   bare ground: the filter runs in sRGB (in the default linearRGB the noise's mean sits well above
   mid grey and the whole page lifted about two levels), and overlay is proportional to what is
   under it, so pure black stays pure black and nothing is tinted: the ground's mean colour is
   unchanged to within 0.03 of a level. SCOPED TO `.bg` ALONE: `.bg` is its own stacking context
   (fixed, z-index), so the blend meets the glows and never the page above it, and print hides
   `.bg` structurally. */
.bg::after{content:"";position:absolute;inset:0;pointer-events:none;mix-blend-mode:overlay;opacity:.55;
  background-size:192px 192px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='192'%3E%3Cfilter id='n' x='0' y='0' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

/* ===================== shared bits ===================== */
.cap{font-size:var(--fs-2);letter-spacing:.18em;text-transform:uppercase;color:var(--grey-45);font-weight:500}
/* ONE E.V.O.S. mark across the whole system (2026-08-17, user): assets/logos/evos-mark.svg,
   their own artwork. The same file is the login art panel's lead (.la-type) and the top bar's
   lockup, so the product names itself the same way everywhere.
   The sub-line keeps the wide-tracked uppercase treatment EVOLV gives OUTDOOR. */
.evos{display:flex;flex-direction:column;line-height:1}
.evos .evos-type{display:block;width:auto;height:15px}
/* The sign-in panel leads with EVOLV's own type logo rather than the product wordmark.
   Height-driven so the 2.92:1 artwork keeps its proportions at any width.
   `align-self:flex-start` matters: the panel is a column flex container, so without it the
   img box is stretched to the full column width and the SVG then centres its artwork inside
   that box, leaving the wordmark floating away from the SIGN IN heading below it. */
.login-type{display:block;align-self:flex-start;height:46px;width:auto;max-width:100%;margin-bottom:22px}
@media (max-width:900px){.login-type{height:38px;margin-bottom:18px}}
.avatar{width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-family:var(--font-display);font-size:var(--fs-3);color:#fff;flex:0 0 auto;border:1px solid var(--line-22);background:linear-gradient(135deg,rgba(255,255,255,.28),rgba(18,40,76,.5))}

/* glint sweep on hover (LED glint) */
.glint{position:relative;overflow:hidden}
.glint>.shine{position:absolute;top:0;left:0;width:60%;height:100%;pointer-events:none;mix-blend-mode:screen;z-index:6;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.14),transparent);
  transform:translateX(-130%) skewX(-14deg);transition:transform .7s var(--ease)}
.glint:hover>.shine{transform:translateX(330%) skewX(-14deg)}
@media (prefers-reduced-motion:reduce){.glint>.shine{display:none}}

/* buttons */
.btn{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:9px;overflow:hidden;cursor:pointer;
  padding:11px 20px;font-family:var(--font-display);text-transform:uppercase;font-size:var(--fs-3);letter-spacing:.06em;
  color:#fff;background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-22);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  transition:all var(--t-micro) var(--ease)}
.btn .lbl{position:relative;z-index:4;display:inline-flex;align-items:center;gap:8px}
.btn::before{content:"";position:absolute;inset:0;z-index:1;opacity:0;transition:opacity var(--t-micro) var(--ease);background:var(--gloss)}
/* halftone dot texture (ported from current build) — visible at rest, lifts on hover */
.btn::after{content:"";position:absolute;inset:0;z-index:2;opacity:.2;pointer-events:none;mix-blend-mode:screen;transition:opacity var(--t-micro) var(--ease);
  background:linear-gradient(180deg,rgba(255,255,255,.5),transparent 18%),radial-gradient(rgba(255,255,255,.3) 26%,transparent 27%) 0 0/3px 3px}
.btn:hover,.btn:focus-visible{border-color:var(--white);outline:none;box-shadow:0 0 26px -8px rgba(255,255,255,.6)}
.btn:hover::before,.btn:focus-visible::before{opacity:.8}
.btn:hover::after,.btn:focus-visible::after{opacity:.5}
.btn:active{transform:translateY(1px)}
/* SOLID IS DARK WITH A WHITE LABEL (2026-08-17, user): the primary action used to be a white
   slab with near-black type, which read as a different system to everything around it and was
   called out on the booking screens. It is now Depth Navy with a full white hairline, so it still
   reads as the loudest thing on the screen while the type stays white like the rest of the build.
   The gloss sweep drops to a hint (it is what made the fill white) and the halftone stays, so the
   button is still a lit EVOLV surface rather than a flat outline. */
.btn.solid{color:#fff;background:var(--depth);border-color:var(--white)}
.btn.solid::before{opacity:.12}
.btn.solid::after{opacity:.34}
.btn.solid .lbl{color:#fff;font-weight:700}
.btn.solid:hover,.btn.solid:focus-visible{background:#173157}
.btn.solid:hover::before,.btn.solid:focus-visible::before{opacity:.3}
.btn.ghost{border-color:var(--line-22)}
.btn.warn{border-color:var(--warn);color:#fff}
.btn.warn .lbl{color:#f4d9a6}
.btn.warn:hover,.btn.warn:focus-visible{border-color:var(--warn);box-shadow:0 0 26px -8px rgba(240,180,80,.6)}
.btn.block{width:100%}
.btn.sm{padding:8px 14px;font-size:var(--fs-2)}
.iconbtn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;cursor:pointer;color:var(--grey);
  background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;transition:all var(--t-micro) var(--ease)}
.iconbtn:hover{border-color:var(--line-40);color:#fff}

/* fields */
.field{margin-bottom:var(--sp-4)}
.field label{display:block;font-size:var(--fs-2);letter-spacing:.1em;text-transform:uppercase;color:var(--grey-45);margin-bottom:7px}
/* THE SITE LIBRARY'S RECORD WRAPS ITS CONTROLS IN .lib-f, NOT .field (2026-09-29, his screenshot: the
   text inputs drew as the browser's white boxes beside styled selects). One rule, two wrappers. */
.field input,.lib-f input{width:100%;padding:11px 13px;background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:#fff;font-family:var(--font-body);font-size:var(--fs-5);outline:none}
.field input:focus,.lib-f input:focus{border-color:var(--hl)}
.field .hint{font-size:var(--fs-2);margin-top:6px;min-height:16px;color:var(--grey-45)}
.field .hint.ok{color:var(--ok)}
.field .hint.warn{color:var(--warn)}
.login-err{color:var(--bad);font-size:var(--fs-3);margin-top:10px;min-height:18px}

/* ===================== login (mirrors current build) ===================== */
.login{position:relative;min-height:100vh;display:grid;grid-template-columns:1.1fr .9fr}
.login-art{position:relative;overflow:hidden;border-right:var(--stroke) solid var(--line-14);display:flex;flex-direction:column;justify-content:space-between;padding:clamp(34px,5vw,72px)}
.login-art .la-head{display:flex;align-items:center;gap:16px}
/* Sized smaller than the EVOLV wordmark it replaced on purpose: that artwork carried the OUTDOOR
   sub-line inside its box, so only 63% of its height was cap height. This mark is all cap height,
   so 40px here reads as the same size on screen as 58px did. */
.login-art .la-type{display:block;width:auto;height:clamp(24px,3vw,40px)}
.login-art .la-big{font-family:var(--font-display);color:#fff;text-transform:uppercase;font-size:var(--fs-hero);line-height:.95;letter-spacing:.01em}
.login-art .la-big span{color:transparent;-webkit-text-stroke:1px var(--line-40)}
.login-art .wm-icon{position:absolute;right:-8%;top:50%;width:60%;opacity:.05;transform:translateY(-50%)}
.login-form{display:flex;flex-direction:column;justify-content:center;padding:clamp(30px,5vw,80px);max-width:600px;width:100%}
.who-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2);margin-top:0;max-height:min(52vh,420px);overflow-y:auto;padding-right:4px}
.who{display:flex;align-items:center;gap:9px;padding:9px;border:var(--stroke) solid var(--line-08);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;cursor:pointer;transition:all var(--t-micro) var(--ease);background:rgba(255,255,255,.012)}
.who:hover{border-color:var(--line-40);background:rgba(255,255,255,.03)}
.who .avatar{width:30px;height:30px;font-size:var(--fs-1)}
.who .wn{font-size:var(--fs-3);color:#fff;line-height:1.05}
.who .wr{font-size:var(--fs-1);color:var(--grey-45)}
.login-pass{margin-top:6px}
.who.picked{margin-bottom:18px;cursor:default;padding:12px}
.who.picked:hover{border-color:var(--line-08);background:rgba(255,255,255,.012)}
.who.picked .avatar{width:40px;height:40px}
.linkbtn{display:block;background:none;border:none;cursor:pointer;color:var(--grey-45);font-family:var(--font-body);
  font-size:var(--fs-3);letter-spacing:.04em;padding:12px 2px 0;transition:color var(--t-micro) var(--ease)}
.linkbtn:hover{color:#fff}
.fresh-test{display:flex;align-items:center;gap:16px;justify-content:space-between;margin-top:22px;padding:16px 18px;border:1px dashed var(--line-22);border-radius:12px 0 12px 0;background:rgba(255,255,255,.015)}
.fresh-test .ft-t{color:#fff;font-weight:600;font-size:var(--fs-4);margin-bottom:3px}
.fresh-test .btn{flex:none}
.fresh-test.testing{border-color:var(--warn);border-style:solid;background:rgba(240,180,80,.06)}
.fresh-test.testing .ft-t{color:#f4d9a6}
@media (max-width:860px){.login{grid-template-columns:1fr}.login-art{display:none}}

/* ===================== app shell ===================== */
/* THE ONE-ROW BAR NEVER CRUSHES (2026-09-29, his screenshot at ~1880px: the icon buttons shrunk
   to slivers, the avatar squashed, Sign out wrapped to two lines). Two causes, both fixed here:
   the side columns were a bare 1fr each, so seven right-hand controls got half of what the nav
   left over; and every `.iconbtn` carries `overflow:hidden`, which makes a flex item's automatic
   minimum ZERO, so flex shrank them to nothing rather than overflow. The sides are now
   `minmax(max-content,1fr)`: equal while there is room (the nav stays centred, the 2026-08-18
   rule), never smaller than their own controls when there is not, the nav giving up a little of
   its centring instead. The tabs came down a cut (his instruction) and the row is MEASURED to fit
   inside the page padding from 1542px with seven sections, the library's a glyph; below that it
   stacks (the block further down, at 1565px). */
.topbar{position:sticky;top:0;z-index:20;display:grid;grid-template-columns:minmax(max-content,1fr) auto minmax(max-content,1fr);
  align-items:center;gap:16px;height:var(--topbar);
  padding:0 var(--pad-x);border-bottom:var(--stroke) solid var(--line-14);
  background:linear-gradient(180deg,rgba(6,10,20,.92),rgba(6,10,20,.72));backdrop-filter:blur(10px)}
.topbar .evos .evos-type{height:16px}
.tb-side{display:flex;align-items:center;gap:12px;min-width:0}
.tb-side>*{flex:0 0 auto}
.tb-side.right{justify-content:flex-end;gap:6px}
.tb-side .btn.sm{white-space:nowrap}
.nav{display:flex;gap:2px;justify-content:center}
.nav-tab{background:none;border:none;cursor:pointer;color:var(--grey-45);font-family:var(--font-display);text-transform:uppercase;
  font-size:var(--fs-2);letter-spacing:.04em;padding:8px 9px;white-space:nowrap;border-radius:var(--notch-sm) 0 var(--notch-sm) 0;transition:all var(--t-micro) var(--ease)}
.nav-tab:hover{color:#fff}
.nav-tab.active{color:#fff;background:rgba(255,255,255,.04);border:var(--stroke) solid var(--line-14)}
/* the Site library's tab is a billboard glyph alone, its words kept off-screen for a reader. The
   glyph is sized off the ROOT, never off the tab's small caps: 1.35em of a .70rem label came out
   at 15px and read as a dim speck (his screenshot). The box stretches to the text tabs' height. */
.nav-tab.nav-icon{display:inline-flex;align-items:center;justify-content:center;padding:3px 10px;margin-right:6px}
.nav-glyph{display:block;width:1.375rem;height:1.375rem}
.nav-glyph svg{display:block;width:100%;height:100%}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
/* --pad-x is the gutter plus 100px of air each side (2026-08-19, user). The gutter itself stays
   as the VERTICAL padding, so only the horizontal changed. */
.wrap{max-width:var(--maxw);margin:0 auto;padding:var(--gutter) var(--pad-x)}
.section-head{display:flex;align-items:center;gap:18px;margin:8px 0 28px}
/* page headers all share --fs-display: Admin was --fs-8 (1.75rem) while the dashboard
   greeting was the clamp, so Admin read smaller than editable body text (2026-08-13) */
.section-head h1{font-size:var(--fs-display);text-transform:uppercase;letter-spacing:.02em}
.section-head .sub{color:var(--grey-45);font-size:var(--fs-4)}

/* ===================== pipeline board ===================== */
.st-grand td{border-top:var(--stroke) solid var(--line-40)}
.st-grand td.camp{color:var(--hl)}
.empty{color:var(--grey-45);font-size:var(--fs-3);padding:8px 2px}
.deal{position:relative;overflow:hidden;border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  padding:var(--sp-3);margin-bottom:var(--sp-3);transition:border-color var(--t-micro) var(--ease);
  background:linear-gradient(180deg,rgba(255,255,255,.035),rgba(18,40,76,.10) 60%,rgba(0,0,0,.22))}
.deal:hover{border-color:var(--line-40)}
/* halftone dot texture on cards — lifts on hover (ported from current build) */
.deal::before,.modal::before{content:"";position:absolute;inset:0;opacity:0;pointer-events:none;mix-blend-mode:screen;transition:opacity .45s var(--ease);
  background:linear-gradient(180deg,rgba(224,224,223,.4),transparent 16%),radial-gradient(rgba(224,224,223,.12) 22%,transparent 23%) 0 0/3px 3px}
.deal:hover::before,.modal:hover::before{opacity:.35}
.deal>*{position:relative;z-index:1}
.deal-name{font-weight:600;color:#fff;margin-bottom:8px;font-size:var(--fs-5);
  display:flex;align-items:baseline;gap:var(--sp-2);flex-wrap:wrap}

/* THE DEAL'S REFERENCE (2026-09-01, user). Quiet beside the name, because it is what you SEARCH
   with and not what you read the row by. Tabular figures so a column of them lines up. */
.deal-ref{font-size:var(--fs-2);letter-spacing:.08em;color:var(--grey-70);font-weight:600;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.deal-ref.lg{display:block;margin-bottom:var(--sp-1);font-size:var(--fs-2)}

/* ---------- the deal timeline ---------- */
/* WHAT HAPPENED AND WHO DID IT. The rail is one line down the left with a dot per entry, so the
   eye reads it as a sequence rather than as a table of rows that happen to be in order. */
.tl{display:flex;flex-direction:column}
.tl-row{display:grid;grid-template-columns:150px 1fr;gap:12px;padding:9px 2px;
  border-bottom:var(--stroke) solid var(--line-08)}
.tl-row:last-child{border-bottom:0}
.tl-when{display:flex;align-items:baseline;gap:var(--sp-2)}
.tl-dot{width:6px;height:6px;flex:0 0 6px;border-radius:50%;background:var(--line-40);
  position:relative;top:-1px}
.tl-detail{color:var(--grey-70);font-size:var(--fs-4);line-height:1.45}
.tl-who{margin-top:2px}

/* A PROOF SAYS WHAT IT IS AND WHOSE IT IS. The camera's own filename drops to a second line in
   small text: kept so nobody loses track of the shot, never the thing it is called. */
.pof-src{display:block;opacity:.62}
.pof-claim{color:var(--grey-70)}
.pof-row.claimed .pof-name{opacity:.85}

/* ---------- site health: one mini card per board ---------- */
/* THE COLOUR IS THE INFORMATION, so it sits on a dot and on the card's own edge rather than
   flooding the surface: a card washed in red stops being a card in this build's language, where
   the page is the dark ground and the cards are the light. */
.health-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(210px,100%),1fr));gap:var(--sp-2)}
.health-card{padding:0;overflow:hidden}
/* A BUTTON IS INLINE-BLOCK UNTIL IT IS TOLD OTHERWISE (2026-08-31), and the whole face is the
   control, so it declares its own width and display. */
.health-face{display:flex;width:100%;align-items:center;gap:var(--sp-2);
  padding:var(--sp-3);background:none;border:0;color:inherit;font:inherit;text-align:left;cursor:pointer}
.health-dot{width:10px;height:10px;flex:0 0 10px;border-radius:50%;background:var(--health-0)}
.health-n{font-weight:600;color:#fff;font-size:var(--fs-4)}
.health-s{white-space:nowrap}
.health-card.h-1 .health-dot{background:var(--health-1)}
.health-card.h-2 .health-dot{background:var(--health-2)}
.health-card.h-3 .health-dot{background:var(--health-3)}
.health-card.h-4 .health-dot{background:var(--health-4)}
.health-card.h-1{border-color:rgba(232,195,107,.42)}
.health-card.h-2{border-color:rgba(232,155,124,.46)}
.health-card.h-3{border-color:rgba(232,140,124,.52)}
.health-card.h-4{border-color:rgba(232,124,124,.62)}
.health-body{padding:0 var(--sp-3) var(--sp-3);display:flex;flex-direction:column;gap:var(--sp-1)}
.health-h{margin-top:var(--sp-2);color:var(--grey-70)}
.health-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--sp-2);
  padding:var(--sp-1) 0;border-top:var(--stroke) solid var(--line-08)}
.health-issue{color:#fff;font-size:var(--fs-4)}

/* ---------- agency or direct ---------- */
/* TWO REAL CHOICES SIDE BY SIDE, each saying what it means for the contact, because the whole point
   is that the rep understands what they are deciding rather than typing a word they were never
   told about. A button is inline-block until told otherwise, so both declare their layout. */
.route-pick{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2)}
.route-opt{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;cursor:pointer;
  padding:var(--sp-2) var(--sp-3);background:rgba(255,255,255,.02);
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  color:var(--grey-70);font:inherit}
.route-opt:hover{border-color:var(--line-40)}
.route-opt.on{border-color:var(--hl);color:#fff;background:var(--hl-12)}
.route-l{font-size:var(--fs-4);font-weight:600}
.route-n{line-height:1.35}
.cb-billed{margin:var(--sp-2) 0 0}
.cb-moves{margin-top:var(--sp-2)}
.cb-move{padding:2px 0}
.cbd-name{display:flex;align-items:baseline;gap:var(--sp-2)}
/* an honest word where there is nothing to look at, on the one screen that must not be guessed at */
.warnline{color:var(--warn);margin:0 0 12px}

/* A CAMPAIGN WAITING ON SOMEBODY (2026-09-01, user: the check was there and hard to see). The card
   carries the attention state on its own edge; --warn is the palette's own "attention / pending",
   the same colour the artwork stage chip already uses, so nothing new was invented for it. */
.deal.awaiting{border-color:rgba(232,195,107,.42)}
/* THE WHOLE CARD IS THE TARGET (2026-09-01, user), so it has to look like one. The name keeps its
   own colour change on hover, which is what tells you the card opens rather than merely highlights. */
.deal.opens{cursor:pointer}
.deal.opens:hover{border-color:var(--line-40)}
.deal.opens:hover .deal-name{color:#fff}
.ops-ask{color:var(--warn);font-size:var(--fs-3);margin:0 0 8px}
.job-acts .act-lead{order:-1}

/* AN ADDED VALUE FLIGHT IS GIVEN, NOT SOLD, and reads as its own kind of row rather than as a
   booking somebody forgot to price. */
.flight-view.added-value{border-left:2px solid var(--ok)}
.st-sitehead .av-add{margin-left:auto}
/* the same dot, riding along on a board heading */
.health-dot.tag{display:inline-block;width:8px;height:8px;flex:0 0 8px;margin-right:var(--sp-1);position:relative;top:-1px}
.health-dot.tag.h-1{background:var(--health-1)}
.health-dot.tag.h-2{background:var(--health-2)}
.health-dot.tag.h-3{background:var(--health-3)}
.health-dot.tag.h-4{background:var(--health-4)}
.deal-meta{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
.chip{font-size:var(--fs-2);padding:3px 9px;border-radius:999px;background:rgba(255,255,255,.04);color:var(--grey-70);border:var(--stroke) solid var(--line-14);text-transform:uppercase;letter-spacing:.04em}
.chip.alt{background:var(--hl-12);color:var(--hl);border-color:transparent}
.chip.brand{color:#fff;border-color:var(--line-40)}
/* a personal permission exception is never allowed to look like the norm */
.chip.warn{background:rgba(240,180,80,.12);color:var(--warn);border-color:transparent}
.deal-rep{font-size:var(--fs-2);color:var(--grey-45)}

/* ===================== sell-through table ===================== */
.st{margin-top:40px}
.st-legend{display:flex;gap:18px;align-items:center;color:var(--grey-45);font-size:var(--fs-3);margin:4px 0 18px}
.st-legend .key{display:inline-flex;align-items:center;gap:7px}
.st-legend .sw{width:14px;height:14px;border-radius:3px;border:var(--stroke) solid var(--line-22)}
.st-legend .sw.booked{background:var(--hl-12);border-color:transparent}
.st-site{margin-top:14px}
.st-sitehead{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.05em;color:var(--hl);font-size:var(--fs-3);margin:0 0 6px 2px}
.st-scroll{overflow-x:auto;border:var(--stroke) solid var(--line-08);border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
table.st-table{border-collapse:collapse;width:100%;font-size:var(--fs-3);white-space:nowrap}
.st-table th,.st-table td{padding:7px 10px;border-bottom:var(--stroke) solid var(--line-08);text-align:right}
.st-table thead th{position:sticky;top:0;background:#0a1120;color:var(--grey-45);font-family:var(--font-display);text-transform:uppercase;font-size:var(--fs-1);letter-spacing:.06em;font-weight:400;z-index:2}
.st-table .lft{text-align:left}
.st-table td.camp,.st-table th.camp{position:sticky;left:0;background:#080d18;text-align:left;color:#fff;z-index:1;min-width:150px}
.st-table thead th.camp{z-index:3}
.st-table .meta{color:var(--grey-45);text-transform:none;letter-spacing:0;font-size:var(--fs-2)}
.st-table td.booked{background:var(--hl-12);color:var(--grey)}
.st-table tr:hover td:not(.camp){background:rgba(255,255,255,.03)}
.st-table tr:hover td.camp{background:#0c1424}
.st-row-sub td{border-top:var(--stroke) solid var(--line-22);font-weight:700;color:#fff;background:rgba(255,255,255,.02)}
.st-row-bud td{color:var(--grey-45)}
.st-row-dif td{font-weight:600}
.st-table td.pos{color:var(--ok)}
.st-table td.neg{color:var(--bad)}

/* ===================== cards (shared) ===================== */
.card{position:relative;overflow:hidden;border:var(--stroke) solid var(--line-14);border-radius:var(--notch) 0 var(--notch) 0;
  /* LIFTED 2026-08-19 (user) with the page darkened underneath. The inner card is lifted LESS
     than a block card on purpose: the block is the lit surface, the cards inside it stay quieter,
     or a page reads as two competing boxes. */
  /* same two-layer rule as the block card: the light goes on the navy, never straight on the dark */
  padding:18px;background:linear-gradient(180deg,rgba(224,224,223,.045),transparent 46%),
    linear-gradient(180deg,rgba(18,40,76,.36),rgba(18,40,76,.20));
  transition:border-color var(--t-micro) var(--ease)}
.card:hover{border-color:var(--line-40)}
/* halftone dot texture on cards — lifts on hover (brand rule: never flat) */
.card::before{content:"";position:absolute;inset:0;opacity:0;pointer-events:none;mix-blend-mode:screen;transition:opacity .45s var(--ease);
  background:linear-gradient(180deg,rgba(255,255,255,.4),transparent 16%),radial-gradient(rgba(255,255,255,.12) 22%,transparent 23%) 0 0/3px 3px}
.card:hover::before{opacity:.3}
.card>*{position:relative;z-index:1}
.ph-t{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.05em;color:#fff;font-size:var(--fs-4);margin-bottom:6px}
.placeholder{margin-top:8px;padding:34px}
.empty.card{color:var(--grey-45);font-size:var(--fs-4);padding:20px}

/* ===================== topbar icons: bell + profile ===================== */
.iconbtn{position:relative;overflow:hidden}
/* A write did not land. Deliberately loud and deliberately not dismissable: every case it
   reports means work is being lost right now. */
.storage-bar{position:fixed;left:0;right:0;bottom:0;z-index:60;display:flex;align-items:center;
  gap:14px;padding:13px var(--pad-x);background:var(--bad);color:#12284C;
  font-family:var(--font-body);font-size:var(--fs-4);line-height:1.35;
  box-shadow:0 -8px 26px rgba(0,0,0,.4)}
.storage-bar.conflict{background:var(--warn)}
.storage-bar .sb-text{flex:1}
.storage-bar .btn{flex:0 0 auto}
@media (max-width:560px){.storage-bar{flex-direction:column;align-items:flex-start;gap:10px}}

/* stroke bell: inherits currentColor from .iconbtn, so it lifts to #fff on hover with the border */
.iconbtn.bell .bell-glyph{display:inline-flex;line-height:0}
.iconbtn.bell .bell-glyph svg{width:18px;height:18px;display:block}
.iconbtn .badge{position:absolute;top:3px;right:3px;min-width:15px;height:15px;padding:0 4px;border-radius:999px;z-index:4;
  background:var(--hl);color:#08122a;font-size:var(--fs-1);font-weight:700;line-height:15px;text-align:center;font-family:var(--font-body)}
.iconbtn.profilebtn{width:auto;padding:2px}
.iconbtn.profilebtn.active{border-color:var(--line-40)}
.avatar.sm{width:32px;height:32px;font-size:var(--fs-1)}
.avatar.xl{width:84px;height:84px;font-size:var(--fs-7)}
.avatar.photo{overflow:hidden;padding:0}
.avatar.photo img{width:100%;height:100%;object-fit:cover;border-radius:50%}

/* ===================== tab strips (workbook tabs) ===================== */
.tabs{display:flex;flex-wrap:wrap;gap:var(--sp-1);margin:0 0 var(--sp-4)}
.tab{position:relative;overflow:hidden;cursor:pointer;padding:8px 14px;color:var(--grey-45);
  background:rgba(255,255,255,.015);border:var(--stroke) solid var(--line-08);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  font-family:var(--font-display);text-transform:uppercase;font-size:var(--fs-2);letter-spacing:.06em;transition:all var(--t-micro) var(--ease)}
.tab .lbl{position:relative;z-index:4}
.tab:hover{color:#fff;border-color:var(--line-40)}
.tab.active{color:#fff;border-color:var(--hl);background:var(--hl-12)}

/* ===================== dashboard ===================== */
/* ONE RHYTHM FOR THE WHOLE COLUMN (2026-09-16, user: "why is there a different amount of space
   between the 3 cards"). The dashboard was a plain div, so its subjects sat sp-5 apart off the
   blocks' own bottom margin while the grid put sp-7 PLUS that margin between its two — a grid
   never collapses margins. Now the column carries the page-stack measure itself (the sp-5
   collapses into it in normal flow) and the grid's children drop the margin the gap replaces. */
.dash-col > * + *{margin-top:var(--sp-7)}
.dash-grid > .dash-block{margin-bottom:0}
.dash-grid{display:grid;grid-template-columns:1fr;gap:var(--sp-7);align-items:start}
/* THE WELCOME (2026-08-19, user): the words alone. The Depth Navy wash and the halftone over it
   were BOTH removed — the greeting leads the page on its own size and its own space, with nothing
   painted behind it. Nothing else in the build takes that treatment either, so the 2026-08-18 rule
   ("the wash belongs to the welcome only") is now simply "no element carries it". */
.dash-head{margin:var(--sp-4) 0 var(--sp-6);text-align:center;
  padding:var(--sp-5) var(--sp-4) var(--sp-4)}
.dash-head .dash-greeting{font-size:var(--fs-greeting);text-transform:uppercase;
  letter-spacing:.02em;line-height:1.15;max-width:26ch;margin:0 auto}
/* THE WORDS THEMSELVES ARE CENTRED (2026-08-19, user). The temporary sizing slider sat in this
   same flex row, so the greeting was pushed left by half the slider's width and never actually
   read as centred. Column direction keeps it true whatever else is ever put beside it. */
.dash-head .greet-wrap{flex-direction:column;align-items:center;justify-content:center;gap:var(--sp-2)}

/* The greeting is editable in place. The pencil sits beside it and is ALWAYS visible: this
   shipped with no affordance at all and could not be found. */
.greet-wrap{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap}
h1.dash-greeting{cursor:text;text-decoration:underline;text-decoration-style:dotted;
  text-decoration-color:transparent;text-underline-offset:6px;
  transition:text-decoration-color var(--t-micro) var(--ease)}
h1.dash-greeting:hover{text-decoration-color:var(--line-40)}
/* flex-basis 100% would mean 100% of the HEIGHT now the wrap is a column: it just sits on its own line. */
.greet-hint{flex:0 0 auto;color:var(--grey-45)}
.dash-head .greeting-edit{display:block;width:100%;max-width:26ch;margin:0 auto;text-align:center;
  font-size:var(--fs-greeting);font-family:var(--font-display);
  background:transparent;border:none;border-bottom:var(--stroke) solid var(--hl);
  color:#fff;padding:0 0 3px;outline:none}
/* no .dash-head .sub any more: the captions under the dashboard headings were removed 2026-08-13 */
.log-who{color:#fff;font-weight:600}
/* A BLOCK HEAD YOU CAN FOLD (2026-08-19, user). Built on the same caret + count parts the archive
   and client-coverage shelves already use, so there is one collapse idiom in the build and not two.
   The heading keeps its h2 and its icon, so the one shared heading rule still sizes it. */
.block-toggle{display:flex;align-items:center;gap:var(--sp-2);width:100%;cursor:pointer;text-align:left;
  background:none;border:none;padding:0;margin-bottom:var(--sp-3);color:inherit}
.block-toggle h2{margin:0}
.block-toggle:hover .arch-caret,.block-toggle:hover .sec-icon{color:var(--hl)}
/* the count is never hidden by the fold: a closed card must still say how much is waiting */
.block-toggle .count{color:var(--grey-45);font-size:var(--fs-2)}
.block-toggle .count.hot{color:var(--hl)}
/* the second count: worth knowing, quieter than what is waiting on you and never merged with it */
.block-toggle .sig-count{color:var(--grey-45)}
.block-toggle .sig-count::before{content:"·";margin-right:var(--sp-2);color:var(--line-22)}
.att{margin-bottom:var(--sp-3)}
.att-text{color:#fff;font-size:var(--fs-5);margin-bottom:4px}
/* why this item reached you: by name, or as one of a group it names (2026-08-26) */
.att-why{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.att-detail{display:flex;align-items:center;gap:12px;margin:10px 0 4px;color:var(--grey-70);font-size:var(--fs-4)}
.att-photo{width:44px;height:44px;border-radius:50%;object-fit:cover;border:1px solid var(--line-22)}
.att-actions{display:flex;gap:10px;margin-top:12px}
.log-row{display:flex;gap:var(--sp-2);align-items:flex-start;padding:var(--sp-3) var(--sp-1);border-bottom:var(--stroke) solid var(--line-08);cursor:pointer;transition:background var(--t-micro) var(--ease)}
.log-row:hover{background:rgba(255,255,255,.02)}
.log-dot{width:7px;height:7px;border-radius:50%;background:var(--line-40);margin-top:7px;flex:0 0 auto}
.log-dot.hot{background:var(--hl);box-shadow:0 0 10px rgba(255,255,255,.7)}
.log-text{color:var(--grey-70);font-size:var(--fs-4);line-height:1.4}

/* ===================== notifications overlay ===================== */
.ntc-modal{max-height:78vh;overflow-y:auto}
.ntc-modal .modal-head{gap:10px}
.ntc-modal .modal-head h2{margin-right:auto}
.ntc-sec{margin-top:16px}
.ntc-sec h3{font-size:var(--fs-3);text-transform:uppercase;letter-spacing:.08em;color:var(--grey-45);margin-bottom:8px}
.ntc{display:flex;gap:12px;align-items:flex-start;padding:var(--sp-3) var(--sp-2);border:var(--stroke) solid transparent;border-bottom-color:var(--line-08);cursor:pointer;transition:all var(--t-micro) var(--ease);border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.ntc:hover{background:rgba(255,255,255,.03);border-color:var(--line-14)}
.ntc.unread .log-text{color:#fff}
.ntc.unread{background:rgba(255,255,255,.05)}
/* THE CLEAR PILL (2026-10-07): one quiet control on every row of a person's lists. A button, so
   it is reachable and announced; styled as the chip beside it so it reads as part of the row's
   meta line and not as an action on the work. It sits at the end of the row on every card. */
.pill-clear{margin-left:auto;flex:0 0 auto;align-self:center;font:inherit;font-size:var(--fs-2);line-height:1;
  text-transform:uppercase;letter-spacing:.06em;padding:4px 10px;border-radius:999px;background:transparent;
  color:var(--grey-45);border:var(--stroke) solid var(--line-14);cursor:pointer;
  transition:color var(--t-micro) var(--ease),border-color var(--t-micro) var(--ease),background var(--t-micro) var(--ease)}
.pill-clear:hover,.pill-clear:focus-visible{color:#fff;border-color:var(--line-40);background:rgba(255,255,255,.05)}
.pill-clear.back{color:var(--grey-70)}
.log-body{flex:1 1 auto;min-width:0}
.ntc.cleared{cursor:default;opacity:.75}
.ntc.cleared:hover{background:none;border-color:transparent;border-bottom-color:var(--line-08)}
.ntc-cleared-toggle{display:flex;align-items:center;gap:8px;width:100%;background:none;border:0;padding:0;cursor:pointer;color:inherit;text-align:left}
.ntc-cleared-toggle h3{margin:0}
.ntc-cleared-toggle .count{color:var(--grey-45);font-size:var(--fs-2)}
.ntc-cleared-toggle .arch-caret{color:var(--grey-45);font-size:var(--fs-4)}
.ntc-cleared .ntc{margin-top:8px}
.ntc-foot{display:flex;justify-content:flex-end;margin-top:12px}
.ntc-actions{display:flex;gap:10px;flex-wrap:wrap;margin:2px 0 6px}

/* ===================== profile ===================== */
.profile{max-width:560px}
.profile-id{display:flex;align-items:center;gap:18px;margin-bottom:20px}
.profile-id .wn.lg{font-size:var(--fs-6);color:#fff;font-weight:600}
.profile-id .wr{color:var(--grey-45);font-size:var(--fs-3)}
.pending{margin-bottom:16px;border-color:var(--warn);max-width:560px}
.field input.file,.field input[type=file]{padding:9px;color:var(--grey-45);font-size:var(--fs-3)}

/* ===================== deal flow: the pipeline (the intake card went on 2026-10-08) ===================== */
.pipeline{margin-bottom:46px}
.pipeline h2{margin-bottom:12px}

/* Archive: closed deals a director has filed away. A quiet one-line shelf that expands, not
   a fifth pipeline column — it is reference, and it must not compete with live work. */
.archive{margin:-18px 0 36px}
.arch-head{display:flex;align-items:center;gap:10px;width:100%;cursor:pointer;text-align:left;
  padding:10px 14px;background:rgba(255,255,255,.012);
  border:var(--stroke) solid var(--line-08);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  transition:border-color var(--t-micro) var(--ease),background var(--t-micro) var(--ease)}
.arch-head:hover{border-color:var(--line-22);background:rgba(255,255,255,.03)}
.arch-caret{color:var(--grey-45);font-size:var(--fs-5);line-height:1;
  transition:transform var(--t-micro) var(--ease)}
.arch-caret.open{transform:rotate(90deg)}
.arch-title{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.08em;
  font-size:var(--fs-3);color:var(--grey-70)}
.arch-head .count{color:var(--grey-45);font-size:var(--fs-2)}
.arch-sub{margin-left:auto;text-align:right}
.arch-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(240px,100%),1fr));gap:var(--sp-3);
  margin-top:12px;opacity:.72;transition:opacity var(--t-micro) var(--ease)}
.arch-grid:hover{opacity:1}
.arch-when{margin-top:8px;padding-top:7px;border-top:var(--stroke) solid var(--line-08)}
@media (max-width:560px){.arch-sub{display:none}}

/* client coverage: one compact row per live deal, no figures anywhere on it.
   THE LIST OWNS THE TRACKS AND EVERY ROW IS A SUBGRID OF IT: a row that is its own grid sizes its
   auto tracks for itself, so column two onwards drifts with the width of that row's badge and rep.
   The literal template on the row is the fallback for a browser without subgrid. */
.cov-rows{display:grid;grid-template-columns:minmax(140px,1.1fr) minmax(120px,1.4fr) auto auto;column-gap:14px;margin-top:var(--sp-3)}
.cov-rows>.cap{grid-column:1/-1}
.cov-row{display:grid;grid-column:1/-1;grid-template-columns:minmax(140px,1.1fr) minmax(120px,1.4fr) auto auto;grid-template-columns:subgrid;
  gap:14px;align-items:center;padding:var(--sp-3) 12px;cursor:pointer;
  border-bottom:var(--stroke) solid var(--line-08);transition:background var(--t-micro) var(--ease)}
.cov-row:hover{background:rgba(255,255,255,.03)}
.cov-acc{display:flex;flex-direction:column;gap:2px;min-width:0}
.cov-acc-name{color:#fff;font-size:var(--fs-4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cov-flag{font-size:var(--fs-1);text-transform:uppercase;letter-spacing:.06em;color:var(--warn)}
.cov-brand{color:var(--grey-70)}
.cov-deal{color:var(--grey-70);font-size:var(--fs-4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cov-rep{font-size:var(--fs-2);color:var(--grey-45);text-align:right;white-space:nowrap}
.cov-rep.me{color:var(--hl)}
/* a clash row paints no tint: the amber flag on the account is the whole signal, and `.clash` on
   the row stays for the sort and the harness */

/* ---------- the oversight card: my campaigns (2026-09-08) ----------
   the same shape as coverage: the shared tab strip, the shared search control, the list owning the
   tracks and each row a subgrid of it */
.ov-body{display:grid;grid-template-columns:auto minmax(140px,1.4fr) minmax(100px,1fr) auto auto auto auto;column-gap:14px;margin-top:var(--sp-3)}
.ov-body>.empty,.ov-body>.btn{grid-column:1/-1}
.ov-row{display:grid;grid-column:1/-1;grid-template-columns:auto minmax(140px,1.4fr) minmax(100px,1fr) auto auto auto auto;grid-template-columns:subgrid;
  gap:14px;align-items:center;width:100%;text-align:left;padding:var(--sp-3) 12px;cursor:pointer;
  background:none;border:0;color:inherit;font:inherit;
  border-bottom:var(--stroke) solid var(--line-08);transition:background var(--t-micro) var(--ease)}
.ov-row:hover{background:rgba(255,255,255,.03)}
.ov-name{color:#fff;font-size:var(--fs-4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ov-val{font-size:var(--fs-3);white-space:nowrap;text-align:right}
.ov-flags{color:var(--grey-45);white-space:nowrap}
@media (max-width:760px){.ov-body{grid-template-columns:auto 1fr auto}
  .ov-row{grid-template-columns:auto 1fr auto;grid-template-columns:subgrid;row-gap:4px}
  .ov-row .cap{display:none}.ov-row .ov-val{display:block}}

/* a line from the books, opened (2026-10-08) */
.book-info-row{display:grid;grid-template-columns:minmax(120px,180px) 1fr;gap:12px;padding:6px 0;border-bottom:var(--stroke) solid var(--line-08)}
.book-info-grid td{font-size:var(--fs-2);white-space:nowrap;padding:6px 8px}
.book-info .modal-head .chip{margin-bottom:6px;display:inline-block}

/* how a flight runs (2026-10-08): the choice, its hours or share, and the seven days */
.runs{display:flex;flex-direction:column;gap:var(--sp-3);margin-top:var(--sp-3)}
.runs-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));gap:var(--sp-3)}
.runs-days{display:flex;flex-wrap:wrap;gap:6px 14px}
.runs-day{display:inline-flex;align-items:center;gap:6px}

/* a deal named in a sentence or on a chip opens it for the directors and Finance (2026-10-08) */
.linkbtn.deal-link{display:inline;text-transform:none;letter-spacing:0;font-size:inherit;color:var(--hl);
  text-decoration:underline;text-underline-offset:2px}
.chip.opens{cursor:pointer}
.chip.opens:hover{border-color:var(--hl);color:#fff}

/* ---------- Operations, On the books (2026-10-08): the campaigns still flighting or to flight ----------
   one row a campaign, the tracks fixed so the columns line up row to row; a director's row is a
   button that opens the correction, the viewer's is plain */
.bk-card{margin-top:var(--sp-3)}
.bk-card .act-controls{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.bk-rep-pick{max-width:260px}
.bk-body{margin-top:var(--sp-3)}
.bk-row{display:grid;grid-template-columns:minmax(0,2.2fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1.4fr) 128px 116px 40px;
  gap:14px;align-items:center;width:100%;text-align:left;padding:var(--sp-3) 12px;
  background:none;border:0;color:inherit;font:inherit;
  border-bottom:var(--stroke) solid var(--line-08);transition:background var(--t-micro) var(--ease)}
button.bk-row{cursor:pointer}
button.bk-row:hover{background:rgba(255,255,255,.03)}
.bk-main{display:flex;flex-direction:column;gap:6px;min-width:0}
.bk-name{color:#fff;font-size:var(--fs-4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bk-chips{display:flex;flex-wrap:wrap;gap:6px}
.bk-rep{font-size:var(--fs-3);color:#fff}
.bk-rep.none{color:var(--warn)}
.bk-val{font-size:var(--fs-3);white-space:nowrap;text-align:right}
.bk-edit{font-size:var(--fs-2);color:var(--grey-45);text-align:right}
button.bk-row:hover .bk-edit{color:var(--hl)}
.bk-edit-card{margin-top:var(--sp-3);display:flex;flex-direction:column;gap:6px}
.bk-trail{margin-top:var(--sp-4);display:flex;flex-direction:column}
.bk-trail-row{display:flex;flex-direction:column;gap:2px;padding:var(--sp-2) 0;border-bottom:var(--stroke) solid var(--line-08)}
.gate-modal.bk-modal{width:min(980px,96vw)}
.bk-fields{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:14px}
.bk-grid-wrap{overflow-x:auto;margin-top:var(--sp-3)}
.bk-grid{border-collapse:collapse;width:100%}
.bk-grid th{font-size:var(--fs-2);color:var(--grey-45);font-weight:400;text-align:left;padding:6px 8px;white-space:nowrap}
.bk-grid td{padding:4px 6px}
.bk-cell{width:100%;min-width:96px}
.bk-sum{display:block;margin-top:var(--sp-3);font-size:var(--fs-4);color:#fff;text-align:right}
@media (max-width:760px){.bk-row{grid-template-columns:1fr auto;row-gap:4px}
  .bk-row .cap{display:none}.bk-row .bk-edit{display:none}
  .bk-fields{grid-template-columns:1fr}}

@media (max-width:640px){.cov-rows{grid-template-columns:1fr auto}
  .cov-row{grid-template-columns:1fr auto;grid-template-columns:subgrid;row-gap:4px}.cov-deal{grid-column:1/-1}}
.deal.glint{cursor:pointer}
.dc-badge{display:inline-block;margin-left:8px;font-size:var(--fs-1);color:var(--hl);letter-spacing:.04em}

/* deal / new-deal modal. Widths are written as `.modal.x` ON PURPOSE (do not simplify): the
   base `.modal{width:480px}` rule is declared later in this file, so a bare `.deal-modal`
   selector ties on specificity and loses — which is exactly why every popup used to render
   at 480px and feel cramped. The booking modal is wider still: a flight's month cells need
   the room. */
.modal.deal-modal{width:660px;max-width:100%}
.modal.booking-modal{width:1040px;max-width:100%}
.modal.ntc-modal{width:560px;max-width:100%}
.modal.crop-modal{width:420px;max-width:100%}
/* The document viewer: written as `.modal.doc-viewer` for the same specificity reason as the rest.
   It is the tallest thing in the build on purpose — a CI is only useful if you can read it. */
.modal.doc-viewer{width:980px;max-width:100%;display:flex;flex-direction:column;
  max-height:calc(100vh - 48px);overflow:hidden}
.doc-viewer .modal-head,.doc-viewer .modal-foot{flex:0 0 auto}
.doc-viewer .dv-stage{flex:1 1 auto;min-height:0;margin:var(--sp-2) 0;display:flex;align-items:center;
  justify-content:center;background:rgba(255,255,255,.02);
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;overflow:auto}
.doc-viewer .dv-img{max-width:100%;max-height:calc(100vh - 260px);display:block}
.doc-viewer .dv-frame{width:100%;height:calc(100vh - 260px);border:0;display:block;background:#fff}
.doc-viewer .dv-none{padding:var(--sp-5) var(--sp-3);text-align:center;max-width:46ch}
/* Pinned head (and footer where there is one), only the middle scrolls, so the title stays
   readable and Save is never chopped off however long the content runs. */
.scroll-modal,.booking-modal{display:flex;flex-direction:column;max-height:calc(100vh - 48px);overflow:hidden}
.scroll-modal .modal-scroll,.booking-modal .modal-scroll{flex:1 1 auto;overflow-y:auto;min-height:0;
  padding-right:10px;margin-right:-10px;overscroll-behavior:contain}
.scroll-modal .modal-head,.booking-modal .modal-head{flex:0 0 auto}
.booking-modal .modal-foot{flex:0 0 auto;margin-top:16px;padding-top:16px;border-top:var(--stroke) solid var(--line-14)}
/* the scrollbar itself, kept in the CI (hairline track, no chrome default) */
.modal-scroll::-webkit-scrollbar{width:8px}
.modal-scroll::-webkit-scrollbar-track{background:transparent}
.modal-scroll::-webkit-scrollbar-thumb{background:var(--line-22);border-radius:4px}
.modal-scroll::-webkit-scrollbar-thumb:hover{background:var(--line-40)}
.modal-scroll{scrollbar-width:thin;scrollbar-color:var(--line-22) transparent}
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}
@media (max-width:560px){.two-col{grid-template-columns:1fr}}
/* THE DROPDOWN'S OWN LIST IS DRAWN BY THE OPERATING SYSTEM (2026-09-29, user: on Edge on a Windows
   machine "choose a site to drill in ... the ui block goes white"). A native select's popup follows
   the element's colour scheme, and without one Windows paints it white on white; the date input
   already carried `color-scheme:dark` for the same reason. The options are coloured too, for the
   browsers that honour it. */
.sel,select{color-scheme:dark}
select option{background:#0D1626;color:#fff}
.sel{width:100%;padding:11px 13px;background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:#fff;font-family:var(--font-body);font-size:var(--fs-5);outline:none}
.sel:focus{border-color:var(--hl)}
.ta{width:100%;min-height:70px;resize:vertical;padding:11px 13px;background:rgba(255,255,255,.02);
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:#fff;
  font-family:var(--font-body);font-size:var(--fs-5);outline:none}
.ta:focus{border-color:var(--hl)}
/* a field the form is waiting on: flagged on submit, cleared the moment it is touched */
.field input.bad,.field .sel.bad,input.bad,select.bad{border-color:var(--bad);background:var(--bad-12)}

/* stage badge */
.stage-badge{display:inline-block;margin-top:6px;padding:3px 10px;border-radius:999px;font-size:var(--fs-1);
  text-transform:uppercase;letter-spacing:.08em;font-family:var(--font-display);border:var(--stroke) solid var(--line-22);color:var(--grey-70)}
.stage-badge.stage-proposal{color:var(--info);border-color:transparent;background:var(--info-12)}
.stage-badge.stage-negotiation{color:var(--warn);border-color:transparent;background:rgba(240,180,80,.14)}
.stage-badge.stage-won{color:var(--ok);border-color:transparent;background:rgba(120,220,150,.14)}
.stage-badge.stage-lost{color:var(--bad);border-color:transparent;background:rgba(240,120,120,.12)}

/* deal meta grid */
.dm-meta{margin:12px 0 4px;border-top:var(--stroke) solid var(--line-08)}
.dm-row{display:grid;grid-template-columns:150px 1fr;gap:12px;padding:9px 2px;border-bottom:var(--stroke) solid var(--line-08)}
.dm-k{font-size:var(--fs-2);text-transform:uppercase;letter-spacing:.1em;color:var(--grey-45);padding-top:2px}
.dm-v{color:#fff;font-size:var(--fs-4)}
.dm-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:16px 0 4px}
.req-note{width:100%;padding:9px 12px;margin-bottom:4px;border:var(--stroke) solid var(--warn);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  background:rgba(240,180,80,.08);color:#f4d9a6;font-size:var(--fs-3)}
.dm-section{margin-top:20px;padding-top:16px;border-top:var(--stroke) solid var(--line-14)}
.dm-section h3{font-size:var(--fs-3);text-transform:uppercase;letter-spacing:.08em;color:var(--grey-45);margin-bottom:12px}

/* comments */
.comment-add{display:flex;gap:10px;align-items:flex-start;margin-bottom:16px}
.comment-add .ta{min-height:44px}
.comment-add .btn{flex:0 0 auto;align-self:stretch}
.comment-list{display:flex;flex-direction:column;gap:12px}
.comment{border-left:2px solid var(--line-22);padding:2px 0 2px 12px}
.comment-head{display:flex;gap:10px;align-items:baseline;margin-bottom:3px}
.comment-who{color:#fff;font-size:var(--fs-4);font-weight:600}
.comment-text{color:var(--grey-70);font-size:var(--fs-4);line-height:1.45;white-space:pre-wrap}
.att.clickable{cursor:pointer}
.att.clickable:hover{border-color:var(--line-40)}

input[type=date]{width:100%;padding:10px 13px;background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:#fff;font-family:var(--font-body);font-size:var(--fs-5);outline:none;color-scheme:dark}
input[type=date]:focus{border-color:var(--hl)}
.warns{max-height:300px;overflow-y:auto;border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.warn-row{padding:8px 12px;border-bottom:var(--stroke) solid var(--line-08);font-size:var(--fs-3);color:var(--warn)}

/* ===================== photo circle cropper ===================== */
.crop-wrap{display:flex;justify-content:center;margin-bottom:14px}
.crop-canvas{cursor:grab;touch-action:none;border:var(--stroke) solid var(--line-22);border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.crop-canvas:active{cursor:grabbing}
.crop-zoom{width:100%;accent-color:#8fb7ff}

/* ===================== availability table + summary extras ===================== */
.av .st-sitehead{color:#fff}
.av-table th.day{min-width:26px;padding:7px 6px;text-align:center}
.av-table td{text-align:center;padding:6px}
.av-table td.camp{min-width:190px}
.av-table td.halfslot{background:rgba(255,255,255,.07);color:var(--grey-70)}
.st-legend .sw.halfslot{background:rgba(255,255,255,.07);border-color:transparent}
.av-table td.note{color:var(--warn);font-size:var(--fs-2);text-transform:uppercase;letter-spacing:.05em;min-width:110px}
.av-table th.note-h{min-width:110px}
.qgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-4);margin-top:var(--sp-4)}
@media (max-width:860px){.qgrid{grid-template-columns:repeat(2,1fr)}}
.qcard .qv{font-family:var(--font-display);color:#fff;font-size:var(--fs-6);margin:2px 0 6px}
/* a figure of zero draws nothing (2026-10-29, user), so an empty value block keeps its line and the tile its height */
.qv:empty::before,.sc-fig-v:empty::before,.sc-count-v:empty::before,.fv-val:empty::before,.fv-b-val:empty::before,.ov-val:empty::before,.bk-val:empty::before,.up-val:empty::before{content:"\00a0"}
.repcat{display:grid;grid-template-columns:220px 1fr;gap:16px;align-items:start}
@media (max-width:760px){.repcat{grid-template-columns:1fr}}
.rc-col h3{font-size:var(--fs-4);text-transform:uppercase;letter-spacing:.08em;color:var(--grey-45);margin-bottom:10px}
.rc-item{padding:7px 4px;border-bottom:var(--stroke) solid var(--line-08);color:var(--grey-70);font-size:var(--fs-4)}
.rc-two{display:grid;grid-template-columns:1fr 1fr;gap:0 22px}
@media (max-width:640px){.rc-two{grid-template-columns:1fr}}

/* ===================== modal + toast ===================== */
.overlay{position:fixed;inset:0;background:rgba(3,6,12,.66);backdrop-filter:blur(3px);display:flex;align-items:center;justify-content:center;padding:24px;z-index:60;
  overflow-y:auto}
/* Baseline: a modal never grows past the viewport, and it scrolls instead of clipping.
   `overflow:hidden` here would silently win over any later overflow-y on a variant, so the
   axes are set separately: x hidden (keeps the cut corners clean), y auto. */
.modal{position:relative;overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - 48px);
  width:480px;max-width:100%;padding:26px;border:var(--stroke) solid var(--line-22);border-radius:var(--notch) 0 var(--notch) 0;
  background:linear-gradient(180deg,rgba(16,23,43,.96),rgba(8,12,24,.98))}
.modal>*{position:relative;z-index:1}
.modal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
.modal-head h2{font-size:var(--fs-7);text-transform:uppercase;letter-spacing:.02em}
.modal .x{background:none;border:none;color:var(--grey-45);font-size:18px;cursor:pointer}
.modal .x:hover{color:#fff}
.modal-foot{display:flex;justify-content:flex-end;gap:10px;margin-top:22px}
.toast{position:fixed;bottom:28px;left:50%;transform:translate(-50%,20px);opacity:0;z-index:80;
  padding:13px 20px;border:var(--stroke) solid var(--hl);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  background:rgba(16,23,43,.96);color:#fff;font-size:var(--fs-4);transition:all var(--t-micro) var(--ease);box-shadow:0 0 30px -10px rgba(255,255,255,.6)}
.toast.show{transform:translate(-50%,0);opacity:1}

/* ===================== deal documents (status dots + toggles) ===================== */
/* Four sanctioned accent colours, one per document (no new hues beyond the CI accents). */
.doc-dots{display:flex;gap:5px;align-items:center}
.doc-dots.lg{gap:7px}
.doc-dot{width:9px;height:9px;border-radius:50%;background:transparent;
  border:1px solid var(--line-40);box-shadow:none;
  transition:background var(--t-micro) var(--ease),box-shadow var(--t-micro) var(--ease),border-color var(--t-micro) var(--ease)}
.doc-dots.lg .doc-dot{width:12px;height:12px}
.doc-dot.on{border-color:transparent}
.doc-dot.doc-contract.on{background:var(--ok);box-shadow:0 0 7px 1px rgba(91,224,176,.85),0 0 16px rgba(91,224,176,.35)}
.doc-dot.doc-artwork.on{background:var(--info);box-shadow:0 0 7px 1px rgba(143,183,255,.85),0 0 16px rgba(143,183,255,.35)}
.doc-dot.doc-ci.on{background:var(--warn);box-shadow:0 0 7px 1px rgba(232,195,107,.85),0 0 16px rgba(232,195,107,.35)}
.doc-dot.doc-confirmation.on{background:#fff;box-shadow:0 0 7px 1px rgba(255,255,255,.8),0 0 16px rgba(255,255,255,.3)}
.deal-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:8px}
.deal-foot .deal-rep{margin:0}
.dm-sec-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.dm-sec-head h3{margin-bottom:0}
/* A doc marked before file upload existed: on, but hollow, so "no file behind this" reads. */
.doc-dot.on.legacy{background:transparent;box-shadow:none}
.doc-dot.doc-contract.on.legacy{border:1px solid var(--ok)}
.doc-dot.doc-artwork.on.legacy{border:1px solid var(--info)}
.doc-dot.doc-ci.on.legacy{border:1px solid var(--warn)}
.doc-dot.doc-confirmation.on.legacy{border:1px solid rgba(255,255,255,.75)}

/* Document slots: one row per document, showing the attached file and what you can do. */
.doc-slots{display:flex;flex-direction:column;gap:8px;margin-top:12px}
.doc-slot{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:11px 14px;
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  background:rgba(255,255,255,.015);transition:border-color var(--t-micro) var(--ease),background var(--t-micro) var(--ease)}
.doc-slot:hover{border-color:var(--line-40)}
.doc-slot-dot{width:9px;height:9px;border-radius:50%;background:var(--line-22);flex:0 0 auto}
.doc-slot-main{flex:1 1 190px;min-width:0}
.doc-slot-lbl{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.04em;
  font-size:var(--fs-3);color:var(--grey-70)}
.doc-slot.on .doc-slot-lbl{color:#fff}
/* filenames wrap rather than truncate: which file is attached is the point of the row */
.doc-slot-meta{font-size:var(--fs-2);color:var(--grey-45);margin-top:3px;line-height:1.45;
  overflow-wrap:anywhere;word-break:break-word}
.doc-slot-acts{display:flex;align-items:center;flex-wrap:wrap;gap:12px;flex:0 0 auto;margin-left:auto}
.doc-slot.on.doc-contract{border-color:var(--ok);background:var(--ok-12)}
.doc-slot.on.doc-contract .doc-slot-dot{background:var(--ok);box-shadow:0 0 8px rgba(91,224,176,.7)}
.doc-slot.on.doc-artwork{border-color:var(--info);background:var(--info-12)}
.doc-slot.on.doc-artwork .doc-slot-dot{background:var(--info);box-shadow:0 0 8px rgba(143,183,255,.7)}
.doc-slot.on.doc-ci{border-color:var(--warn);background:var(--warn-12)}
.doc-slot.on.doc-ci .doc-slot-dot{background:var(--warn);box-shadow:0 0 8px rgba(232,195,107,.7)}
.doc-slot.on.doc-confirmation{border-color:rgba(255,255,255,.55);background:rgba(255,255,255,.08)}
.doc-slot.on.doc-confirmation .doc-slot-dot{background:#fff;box-shadow:0 0 8px rgba(255,255,255,.6)}
/* Staged: picked but NOT saved. It has to read as provisional, because it is the one state
   where a file can still be dropped. Dashed edge + amber, never the document's own colour. */
.doc-slot.staged{border-style:dashed;border-color:var(--warn);background:var(--warn-12)}
.doc-slot-lbl{display:flex;align-items:center;gap:8px}
.dv-count{font-family:var(--font-body);text-transform:none;letter-spacing:0;
  font-size:var(--fs-1);color:var(--grey-45)}
.doc-staged-note{font-size:var(--fs-2);color:var(--warn);margin-top:5px;overflow-wrap:anywhere}
.doc-foot{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:12px}
.doc-foot .cap{flex:1 1 240px}

/* Version history: every file this slot has ever held. Nothing is ever deleted. */
.doc-versions{display:flex;flex-direction:column;gap:6px;margin:-2px 0 2px;
  padding:10px 14px;border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.012)}
.doc-version{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;font-size:var(--fs-2)}
.dv-n{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;
  font-size:var(--fs-1);color:var(--grey-45);flex:0 0 auto;min-width:78px}
.doc-version.current .dv-n{color:var(--hl)}
.dv-name{color:var(--grey-70);overflow-wrap:anywhere}
.doc-version.current .dv-name{color:#fff}
.dv-meta{margin-left:auto}

.doc-slot.legacy{background:rgba(255,255,255,.015)}
.doc-slot.legacy .doc-slot-dot{background:transparent;box-shadow:none;border:2px solid var(--line-40)}
.doc-slot.legacy .doc-slot-meta{color:var(--warn)}
.linkbtn.danger{color:var(--warn)}
.doc-hint{margin-top:10px;color:var(--warn)}
@media (max-width:560px){
  .doc-slot{flex-wrap:wrap}
  .doc-slot-acts{width:100%;padding-left:21px}
}

/* Finance only: slice the whole sheet by rep, by site, or both. */
.st-filters{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap;margin:2px 0 12px;
  padding:12px 14px;border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.012)}
.st-filters .field{margin-bottom:0;flex:1 1 240px;min-width:0}
.st-filters .btn{flex:0 0 auto}
.st-filter-note{margin:-6px 0 12px;color:var(--hl);text-transform:none;letter-spacing:.04em}
@media (max-width:560px){.st-filters .field{flex:1 1 100%}}

/* Sell Through picker: brackets are TABS (Summary and Reps & Categories sit in the same
   strip), the site is a DROPDOWN. The strip owns the full width and wraps to as many rows as
   it needs, so the site control sits beneath it on its own line rather than being squeezed
   to the right of a two-row strip. */
.st-picker{display:flex;flex-direction:column;align-items:flex-start;gap:12px;margin-bottom:14px}
.st-picker .tabs{margin-bottom:0;width:100%}
/* The sheet's own head: title left, the year it is showing on the right. */
.st-head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--sp-3);flex-wrap:wrap}
.st-head h2{margin-bottom:0}
.st-year,.av-picker .field.yr{margin-bottom:0;min-width:190px}
.st-year-note{margin:var(--sp-2) 0 0;max-width:70ch}
.st-selects{display:flex;gap:12px;flex-wrap:wrap;width:100%}
/* A bracket shows every one of its sites stacked; the note says so, and the back button appears
   only once somebody has drilled into a single site. */
.st-back{margin-bottom:var(--sp-3)}
.st-selects .field{margin-bottom:0;min-width:210px;flex:1 1 260px;max-width:420px}
@media (max-width:720px){.st-selects .field{flex:1 1 100%;min-width:0;max-width:none}}

/* ===================== admin: categories ===================== */
.cat-add{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap;margin-bottom:16px}
.cat-add .field{margin-bottom:0;flex:1 1 260px;max-width:340px}
.cat-rows{display:flex;flex-direction:column;gap:8px}
.cat-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:9px 14px;
  border:var(--stroke) solid var(--line-08);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  background:rgba(255,255,255,.012);transition:border-color var(--t-micro) var(--ease)}
.cat-row:hover{border-color:var(--line-22)}
.cat-row input.cat-name{flex:1 1 220px;min-width:0;background:transparent;border:none;
  color:#fff;font-size:var(--fs-4);padding:4px 0}
.cat-row input.cat-name:focus{outline:none;border-bottom:var(--stroke) solid var(--hl)}
.cat-use{flex:0 0 auto;color:var(--grey-45)}
.cat-acts{display:flex;align-items:center;gap:14px;margin-left:auto;flex:0 0 auto}
@media (max-width:560px){.cat-acts{width:100%;margin-left:0}}

/* ===================== finance: what is still outstanding =====================
   A chase list. Each card is a call to make, so the missing document is the loud part and
   carries that document's own colour. */
/* one column: outstanding, vetting, contracts to produce (2026-08-18, user) */
.fin-landing{display:flex;flex-direction:column;gap:var(--sp-6)}
.fin-landing > *{margin-top:0}
.outstanding{margin-bottom:8px}
.out-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap}
.out-head h2{margin-bottom:0}
/* the POF library's right-hand group: year, month and Add proof aligned and of one height
   (2026-09-16, user, screenshot) */
.pof-tools{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap}
.pof-tools .field{margin-bottom:0;min-width:140px}
.out-filter{margin-bottom:0;min-width:250px}
/* one pile per rep (2026-08-18, user): the name is the heading, so it comes off every card.
   THE PILES STAND SIDE BY SIDE (2026-09-29, his screenshot: each pile was a full-width row
   holding one 260px card, so four fifths of the block was empty). The piles are the grid's
   items now, `auto-fit` so a lone pile or two take the whole width and their cards flow two
   across inside, while four reps read as four columns. A pile's count is a pill beside the
   name, because a bare grey digit read as a stray character. */
.out-groups{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));
  gap:var(--sp-5) var(--sp-4);align-items:start}
.out-group{min-width:0}
.out-group-head{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.out-group-head .ogh-rep{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;
  font-size:var(--fs-3);color:#fff}
.out-group-head .count{min-width:22px;padding:1px 8px;text-align:center;line-height:1.5;
  color:var(--grey-70);font-size:var(--fs-2);border:var(--stroke) solid var(--line-14);border-radius:999px}
.out-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(260px,100%),1fr));gap:12px}
/* inside a pile the grid's gap is the only spacing: the card's own bottom margin doubled it */
.out-group .deal{margin-bottom:0}
.out-held{margin-top:10px;letter-spacing:.12em}
.out-missing{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 2px}
.out-tag{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;
  font-size:var(--fs-1);padding:4px 9px;border:var(--stroke) solid var(--line-22);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:var(--grey-70)}
.out-tag.doc-contract{border-color:var(--ok);color:var(--ok);background:var(--ok-12)}
.out-tag.doc-artwork{border-color:var(--info);color:var(--info);background:var(--info-12)}
.out-tag.doc-ci{border-color:var(--warn);color:var(--warn);background:var(--warn-12)}
/* A NOTE, not a job: artwork is listed where it is missing but Finance does not chase it, so it
   keeps the document's colour and loses the fill that makes the chased ones shout. */
.out-tag.note{background:none;opacity:.62}
@media (max-width:560px){.out-filter{min-width:100%}}

/* Vetting sits under the contract requests, in the same column: both are Finance's own queue. */
.fin-card{margin-top:var(--sp-5)}
.fin-card .deal{margin-bottom:12px}
.fin-card .deal-name.clickable{cursor:pointer}
.vet-items{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 2px}

/* ===================== flights: boards, per-board and per-month money =====================
   The booking modal is wide on purpose: a flight shows its board cards, its dates and a money
   row per board with one cell per month, and none of that reads in a narrow column. */
.linkbtn{background:none;border:none;color:var(--hl);font-size:var(--fs-2);cursor:pointer;text-transform:uppercase;letter-spacing:.06em;padding:0}
.linkbtn:hover{color:#fff}
.linkbtn.danger{color:var(--bad)}
.linkbtn.danger:hover{color:#fff}

.total-field input.big-val{font-size:var(--fs-6);padding:14px 15px;letter-spacing:.02em}
.three-col{display:grid;grid-template-columns:1fr 1fr 1fr;gap:0 14px}
@media (max-width:720px){.three-col{grid-template-columns:1fr}}

/* one flight = one burst of the campaign; a break is simply the next flight */
.flights{display:flex;flex-direction:column;gap:14px;margin-bottom:14px}
.flight{padding:16px 18px}

/* board cards: glyph, name, subtitle, tick */
/* ONE SCROLL, NOT TWO (2026-10-07, user: in the wizard "scroll stops just before the last row of
   the selectable sites" for a second). The grid was its own 236px scroll box inside the wizard's
   scroll, so a wheel or a trackpad stuck at its last row until the gesture let go and the outer
   scroll took over. The grid grows now and the wizard's one scroll area carries it. */
.board-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:7px;
  padding:9px;border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.012)}
.board-card{position:relative;display:flex;flex-direction:column;gap:2px;cursor:pointer;
  padding:9px 10px 8px;border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.02);
  transition:border-color var(--t-micro) var(--ease),background var(--t-micro) var(--ease)}
.board-card:hover{border-color:var(--line-40);background:rgba(255,255,255,.04)}
.board-card input{position:absolute;opacity:0;width:0;height:0}
.board-card .bc-icon{display:block;width:18px;height:18px;color:var(--grey-45);margin-bottom:2px}
.board-card .bc-icon svg{width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:1.3;
  stroke-linecap:round;stroke-linejoin:round}
.board-card .bc-icon .bc-lines{stroke-width:1}
.bc-name{color:#fff;font-size:var(--fs-3);letter-spacing:.01em}
.bc-sub{color:var(--grey-45);font-size:var(--fs-2);line-height:1.3;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.bc-tick{position:absolute;top:8px;right:9px;width:13px;height:13px;border-radius:50%;
  border:var(--stroke) solid var(--line-22);transition:all var(--t-micro) var(--ease)}
.board-card input:checked ~ .bc-tick{background:var(--hl);border-color:var(--hl);
  box-shadow:0 0 10px rgba(255,255,255,.45)}
.board-card input:checked ~ .bc-name{color:#fff}
.board-card:has(input:checked){border-color:var(--hl);background:var(--hl-12)}
.board-card:has(input:checked) .bc-icon{color:var(--hl)}
.board-card input:focus-visible ~ .bc-tick{border-color:var(--hl)}

/* money grid: one row per board, one cell per month the flight touches */
.alloc-rows{display:flex;flex-direction:column;gap:10px;margin:4px 0 12px}
.alloc-row{display:grid;grid-template-columns:1fr 150px;gap:10px 12px;align-items:start;
  padding:12px 14px;border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.015)}
.alloc-board{display:flex;flex-direction:column;gap:4px;align-items:flex-start;padding-top:19px}
.ab-name{color:#fff;font-size:var(--fs-4);overflow-wrap:anywhere}
.alloc-months{grid-column:1 / -1;display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:8px}
.alloc-cell label{display:block;font-size:var(--fs-2);letter-spacing:.08em;text-transform:uppercase;
  color:var(--grey-45);margin-bottom:5px}
.alloc-cell input{width:100%}
.alloc-note{grid-column:1 / -1}
/* the deal total, restated on the split step where the figures are actually typed (2026-08-26) */
.wz-split-total{display:flex;align-items:flex-end;gap:var(--sp-2);flex-wrap:wrap;
  padding-bottom:var(--sp-2);margin-bottom:var(--sp-2);
  border-bottom:var(--stroke) solid var(--line-08)}
.wz-split-total .field{flex:0 1 240px}
.wz-split-total .cap.match{color:var(--ok)}
.wz-split-total .cap.mismatch{color:var(--warn)}
.tally{margin-top:2px}
.tally.grand{font-size:var(--fs-4);padding:10px 0 2px}
.tally.match,.alloc-note.match{color:var(--ok)}
.tally.mismatch,.alloc-note.mismatch{color:var(--warn)}

/* flights as read on the deal */
.flight-view{padding:10px 12px;border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;margin-bottom:8px;background:rgba(255,255,255,.015)}
.fv-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:6px}
.fv-n{font-family:var(--font-display);font-size:var(--fs-3);letter-spacing:.08em;text-transform:uppercase;color:#fff}
.fv-val{margin-left:auto;color:#fff;font-size:var(--fs-4)}
.fv-board{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;padding:5px 0;
  border-top:var(--stroke) solid var(--line-08)}
.fv-b-name{color:var(--grey-70);font-size:var(--fs-4);overflow-wrap:anywhere}
.fv-b-val{color:#fff;font-size:var(--fs-4)}
.fv-b-months{display:flex;gap:6px;flex-wrap:wrap;margin-left:auto}
.fv-m{font-size:var(--fs-2);padding:2px 8px;border-radius:999px;background:rgba(255,255,255,.04);
  color:var(--grey-70);border:var(--stroke) solid var(--line-08)}
.fv-m.zero{opacity:.35}

/* a proposed value change, waiting on the Finance Director */
.value-req{margin-top:12px;padding:12px 14px;border:var(--stroke) solid var(--warn);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:var(--warn-12)}
.vr-text{color:#fff;font-size:var(--fs-4);margin-bottom:3px;overflow-wrap:anywhere}

.split-view{margin-top:10px;padding-top:8px;border-top:var(--stroke) solid var(--line-08)}
.split-view-h{margin-bottom:6px}
.split-view-row{display:flex;justify-content:space-between;padding:4px 0;font-size:var(--fs-4);color:var(--grey-70)}
.split-view-val{color:#fff}

/* ===================== admin: client book ===================== */
.cb-list{display:flex;flex-direction:column;gap:8px}
.cb-item{padding:0;overflow:visible}
.cb-head{display:flex;align-items:center;gap:16px;padding:14px 16px;cursor:pointer;flex-wrap:wrap}
.cb-item.open .cb-head{border-bottom:var(--stroke) solid var(--line-08)}
.cb-id{flex:1 1 200px;min-width:0}
.cb-name{color:#fff;font-size:var(--fs-5);overflow-wrap:anywhere}
.cb-contact{flex:1 1 200px;min-width:0;overflow-wrap:anywhere;letter-spacing:.04em;text-transform:none}
.cb-stat{display:flex;gap:6px;flex-wrap:wrap}
.cb-caret{width:20px;text-align:center;color:var(--grey-45);font-size:var(--fs-5);flex:0 0 auto}
.cb-body{padding:16px}
.cb-acts{display:flex;gap:10px;margin-bottom:6px}
.cb-sub{font-family:var(--font-display);font-size:var(--fs-2);letter-spacing:.12em;text-transform:uppercase;
  color:var(--grey-45);margin:18px 0 8px;font-weight:700}
.cb-deals{display:flex;flex-direction:column;gap:6px}
.cb-deal{display:flex;align-items:center;gap:10px;flex-wrap:wrap;cursor:pointer;padding:9px 12px;
  border:var(--stroke) solid var(--line-08);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  background:rgba(255,255,255,.015);transition:border-color var(--t-micro) var(--ease)}
.cb-deal:hover{border-color:var(--line-40)}
.cbd-name{color:#fff;font-size:var(--fs-4);overflow-wrap:anywhere}
.cbd-val{margin-left:auto;color:#fff;font-size:var(--fs-4)}

/* ===================== admin: team ===================== */
.tm-list{display:flex;flex-direction:column;gap:8px}
.tm-item{display:flex;align-items:center;gap:14px;padding:12px 16px;flex-wrap:wrap}
.tm-item.off{opacity:.5}
.tm-id{flex:1 1 220px;min-width:0}
.tm-name{color:#fff;font-size:var(--fs-5);overflow-wrap:anywhere}
.tm-flags{display:flex;gap:6px;flex-wrap:wrap}
.tm-acts{display:flex;gap:14px;margin-left:auto}
.flag-row{display:flex;align-items:flex-start;gap:9px;cursor:pointer;margin-bottom:8px;
  font-size:var(--fs-4);color:var(--grey-70);text-transform:none;letter-spacing:0}
.flag-row input{accent-color:#8fb7ff;flex:0 0 auto;margin-top:3px;width:auto}

/* ===================== activity search + filter ===================== */
.act-controls{display:flex;gap:10px;margin-bottom:12px}
.act-search{flex:1 1 auto;padding:9px 12px;background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:#fff;font-family:var(--font-body);font-size:var(--fs-4);outline:none}
.act-search:focus{border-color:var(--hl)}
.act-filter{flex:0 0 auto;width:auto;min-width:140px}
.act-rows{display:flex;flex-direction:column}

/* Hairline rules are GONE (2026-08-13, user): they were not helping legibility. Neither the one
   above the page header nor the ones between blocks. Spacing does the separating now, so there is
   no .rule, no .sec-divider and no scroll observer to draw them in. */

/* a touch more air around section blocks + headings */
.section-head{margin-bottom:var(--sp-5)}
/* a head with no title left, only its action: it does not need a title's worth of space under it */
.section-head.bare{margin:0 0 14px;min-height:0}
.dash-block{margin-bottom:var(--sp-5)}

/* top-nav back button */
.backbtn .back-glyph{font-size:20px;line-height:1;font-weight:700}

/* ===================== availability asset/month pickers ===================== */
.av-picker{display:flex;gap:16px;flex-wrap:wrap;margin:8px 0 18px}
.av-picker .field{margin-bottom:0;min-width:240px}
@media (max-width:560px){.av-picker .field{min-width:100%}}

/* ===================== sell-through % achieved row ===================== */
.st-row-pct td{font-weight:700;border-top:var(--stroke) solid var(--line-14)}
.st-row-pct td.camp,.st-row-pct td.meta.lft{color:var(--grey-70);font-weight:600}

/* ===================== admin page ===================== */
.admin-cards{margin-bottom:26px}
.admin-cards .qv{font-size:var(--fs-7)}
.admin-budget-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
@media (max-width:860px){.admin-budget-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:520px){.admin-budget-grid{grid-template-columns:1fr}}
.abg-item{padding:12px;border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.012)}
.abg-item.set{border-color:var(--hl);background:var(--hl-12)}
.abg-item label{display:block;font-size:var(--fs-2);letter-spacing:.08em;text-transform:uppercase;color:var(--grey-45);margin-bottom:7px}
.abg-item .cap{margin-top:6px}
.abg-item.set .cap{color:var(--hl)}

/* ===================== login: live restore point ===================== */
.restore-point{margin-top:12px}
/* Both panels in this strip (test mode, restore point) put their buttons in this wrapper. */
.fresh-test .rp-btns{display:flex;flex-direction:column;gap:8px;flex:0 0 auto}
.fresh-test .rp-btns .btn .lbl{white-space:nowrap}
@media (min-width:520px){.fresh-test .rp-btns{flex-direction:row}}

/* ===================== finance contract requests ===================== */

/* Finance job actions: what this job needs next, on the card itself. */
.job-acts{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px;
  padding-top:10px;border-top:var(--stroke) solid var(--line-14)}

/* ===================== Won revenue with nowhere to sit on the sheet ===================== */
.unplaced{margin:14px 0 4px;padding:14px 16px;
  border:var(--stroke) solid rgba(232,195,107,.34);border-radius:var(--notch) 0 var(--notch) 0;
  background:rgba(232,195,107,.07)}
/* Money that is simply on another year's sheet is not a warning: it drops the amber entirely and
   reads as a note. Only genuinely stranded revenue keeps the alarm. */
.unplaced.quiet{border-color:var(--line-14);background:rgba(255,255,255,.02)}
.up-elsewhere{margin:0}
.unplaced-head{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.04em;
  font-size:var(--fs-3);color:var(--warn);margin-bottom:5px}
.unplaced-list{margin-top:10px;display:flex;flex-direction:column;gap:5px}
.unplaced-row{display:grid;grid-template-columns:1.4fr .8fr 1.6fr auto;gap:12px;align-items:baseline;
  font-size:var(--fs-3);color:var(--grey-70)}
.unplaced-row .up-deal{color:#fff;overflow-wrap:anywhere}
.unplaced-row .up-why{color:var(--grey-45)}
.unplaced-row .up-val{color:var(--warn);text-align:right;font-variant-numeric:tabular-nums}
@media (max-width:720px){
  .unplaced-row{grid-template-columns:1fr auto}
  .unplaced-row .up-why{grid-column:1 / -1}
}

/* AND SMOOTH SCROLLING IS MOTION TOO (2026-09-03). A page that glides when somebody has asked the
   system for no animation is exactly what that setting is about, and it is the one kind of motion
   you cannot look away from. The cursor goes with it: it is a thing that follows you. */
@media (prefers-reduced-motion:reduce){
  *{transition:none!important}
  html{scroll-behavior:auto}
}

/* ===================== deal wizard ===================== */
.booking-modal .wz-dots{display:flex;gap:6px;flex-wrap:wrap;margin:10px 0 16px}
.wz-dot{display:flex;align-items:center;gap:0;padding:6px 12px;cursor:default;
  background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  transition:border-color var(--t-micro) var(--ease),background var(--t-micro) var(--ease)}
.wz-dot-l{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.07em;
  font-size:var(--fs-1);color:var(--grey-45);white-space:nowrap}
.wz-dot.done{cursor:pointer;border-color:var(--line-22)}
.wz-dot.done:hover{background:rgba(255,255,255,.05)}
.wz-dot.done .wz-dot-l{color:var(--grey-70)}
.wz-dot.on{border-color:var(--hl);background:var(--hl-12)}
.wz-dot.on .wz-dot-l{color:#fff}

.wz-card{display:flex;flex-direction:column}
.wz-lead{font-family:var(--font-display);font-size:var(--fs-5);color:#fff;letter-spacing:.01em;margin-bottom:4px}
.wz-lead.sm{font-size:var(--fs-5);margin-top:20px}
.wz-sub{margin-bottom:16px}
.wz-draft{color:var(--hl);margin-bottom:10px;text-transform:none;letter-spacing:.04em}
.wz-warn{color:var(--warn);text-transform:none;letter-spacing:.04em;margin-top:8px}
.wz-issue{color:var(--warn);text-transform:none;letter-spacing:.04em;margin-right:auto;max-width:60%}
.wz-foot{align-items:center;gap:12px}
.wz-flight-acts{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:18px;
  padding-top:14px;border-top:var(--stroke) solid var(--line-08)}

.grp-bar{display:flex;flex-wrap:wrap;gap:7px}
.grp-btn{display:inline-flex;align-items:center;gap:8px;cursor:pointer;padding:7px 12px;
  background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  transition:border-color var(--t-micro) var(--ease),background var(--t-micro) var(--ease)}
.grp-btn .lbl{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;
  font-size:var(--fs-1);color:var(--grey-70)}
.grp-btn .grp-n{font-size:var(--fs-1);color:var(--grey-45)}
.grp-btn:hover{border-color:var(--line-40)}
.grp-btn.on{border-color:var(--hl);background:var(--hl-12)}
.grp-btn.on .lbl{color:#fff}
.grp-btn.on .grp-n{color:var(--hl)}

.wz-summary{display:flex;flex-direction:column;gap:10px;margin-top:6px}
.wz-sum-row{display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  padding-bottom:8px;border-bottom:var(--stroke) solid var(--line-08);font-size:var(--fs-4);color:var(--grey-70)}
.wz-sum-row strong{color:#fff;font-weight:600}
.wz-sum-flight{padding:12px 14px;border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.015)}
.wz-sum-fh{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:8px}
.wz-sum-fh span:first-child{font-family:var(--font-display);text-transform:uppercase;
  letter-spacing:.07em;font-size:var(--fs-1);color:#fff}
.wz-sum-fh strong{margin-left:auto;color:#fff}
.wz-sum-boards{display:flex;flex-wrap:wrap;gap:6px}
.btn.is-off{opacity:.5}

/* the leave gate sits above the wizard it interrupts */
.overlay.gate{z-index:70;background:rgba(3,6,12,.5)}
.gate-modal{width:420px}

/* a Won campaign still short of its CI or contract: amber on the MONTHS IT RUNS, not the whole row */
.st-table tbody tr.st-row-short td.camp{color:var(--warn);font-weight:600}
.st-table tbody tr.st-row-short td.short{background:var(--warn-12);color:var(--warn)}
/* the same shortfall said once, above the tabs, so it is on screen on EVERY view of the sheet and
   not only on the per-site tables that draw campaign rows (2026-08-26) */
.st-short-note{display:block;padding:10px 14px;margin-bottom:var(--sp-2);color:var(--warn);
  border:var(--stroke) solid var(--warn);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  background:var(--warn-12)}
.st-short-note strong{color:var(--warn)}
.st-short-note span{color:var(--grey)}

/* ===================== pipeline: pill nav + one stage at a time ===================== */
.pipe-head{display:flex;align-items:baseline;gap:14px;margin-bottom:14px;flex-wrap:wrap}
.pipe-head .spacer{flex:1 1 auto}
.pipe-head .btn{align-self:center}
.pipe-head h2{margin-bottom:0}
.pipe-pills{display:flex;flex-wrap:wrap;gap:9px;margin-bottom:18px}
.pipe-pill{display:inline-flex;align-items:center;gap:9px;cursor:pointer;padding:9px 16px;
  background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);border-radius:999px;
  transition:border-color var(--t-micro) var(--ease),background var(--t-micro) var(--ease)}
.pipe-pill:hover{border-color:var(--line-40);background:rgba(255,255,255,.045)}
.pp-dot{width:7px;height:7px;border-radius:50%;background:var(--line-40);flex:0 0 auto;
  transition:background var(--t-micro) var(--ease),box-shadow var(--t-micro) var(--ease)}
.pp-l{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.08em;
  font-size:var(--fs-2);color:var(--grey-70)}
.pp-n{font-size:var(--fs-2);color:var(--grey-45);min-width:14px;text-align:right}
.pipe-pill.on .pp-l{color:#fff}
.pipe-pill.stage-proposal .pp-dot{background:var(--info)}
.pipe-pill.stage-negotiation .pp-dot{background:var(--warn)}
.pipe-pill.stage-won .pp-dot{background:var(--ok)}
.pipe-pill.stage-lost .pp-dot{background:var(--bad)}
.pipe-pill.on.stage-proposal{border-color:var(--info);background:var(--info-12)}
.pipe-pill.on.stage-negotiation{border-color:var(--warn);background:var(--warn-12)}
.pipe-pill.on.stage-won{border-color:var(--ok);background:var(--ok-12)}
.pipe-pill.on.stage-lost{border-color:var(--bad);background:var(--bad-12)}
.pipe-pill.on .pp-dot{box-shadow:0 0 8px currentColor}
.pipe-pill.on.stage-proposal .pp-dot{box-shadow:0 0 9px rgba(143,183,255,.9)}
.pipe-pill.on.stage-negotiation .pp-dot{box-shadow:0 0 9px rgba(232,195,107,.9)}
.pipe-pill.on.stage-won .pp-dot{box-shadow:0 0 9px rgba(91,224,176,.9)}
.pipe-pill.on.stage-lost .pp-dot{box-shadow:0 0 9px rgba(232,124,124,.9)}
.pipe-pill.on .pp-n{color:#fff}

/* one stage at a time, so a card gets real room instead of a quarter column */
.pipe-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(290px,100%),1fr));gap:var(--sp-4)}
.pipe-body .empty.card{padding:26px}
@media (max-width:520px){.pipe-grid{grid-template-columns:1fr}}

/* ============================================================================
   Custom cursor (2026-08-13)
   Two SVG data-URIs, nothing else. No JS, no trailing dot, no animation, no
   extra layer to composite: a custom cursor drawn by the compositor costs the
   same as the system one, which is why this stays fast.

   A NORMAL CURSOR'S SHAPE, IN THE CI (2026-09-07, user). It was drawn 13.2 wide
   against 18.3 tall, a ratio of 0.72 where a real OS arrow is nearer 0.58, and
   that fatness is what stopped it reading as a cursor at all. Same seven points,
   real proportions, and the EVOLV treatment is the only thing left doing the
   talking: miter joins rather than the rounded OS arrow, white with a navy
   outline, INVERTED to navy on white over anything clickable so a hit target
   announces itself without a hover effect having to run.
   Hotspot is 2 2, the arrow tip. Every rule keeps a real keyword fallback, so
   a browser that refuses the image still shows the right kind of pointer.
   ============================================================================ */
:root{
  --cur-arrow:url('data:image/svg+xml,%3Csvg xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22 width%3D%2224%22 height%3D%2224%22 viewBox%3D%220 0 24 24%22%3E%3Cpath d%3D%22M3 2 3 17.2 6.9 13.4 9.6 19.6 11.9 18.6 9.3 12.6 13 12.2 Z%22 fill%3D%22%23FFFFFF%22 stroke%3D%22%2310172B%22 stroke-width%3D%221.1%22 stroke-linejoin%3D%22miter%22%2F%3E%3C%2Fsvg%3E') 2 2;
  --cur-point:url('data:image/svg+xml,%3Csvg xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22 width%3D%2224%22 height%3D%2224%22 viewBox%3D%220 0 24 24%22%3E%3Cpath d%3D%22M3 2 3 17.2 6.9 13.4 9.6 19.6 11.9 18.6 9.3 12.6 13 12.2 Z%22 fill%3D%22%2310172B%22 stroke%3D%22%23FFFFFF%22 stroke-width%3D%221.1%22 stroke-linejoin%3D%22miter%22%2F%3E%3C%2Fsvg%3E') 2 2;
}
html,body{cursor:var(--cur-arrow),default}
/* anything clickable: same selectors that already declare cursor:pointer, so the two
   never drift apart. Listed last in the file, so these win without !important. */
.btn,.iconbtn,.who,.linkbtn,.nav-tab,.tab,.log-row,.ntc,.arch-head,
.cov-row,.deal.glint,.att.clickable,.modal .x,.board-card,.cb-head,.cb-deal,.flag-row,
.wz-dot.done,.grp-btn,.pipe-pill,a,summary,select,option,
label[for],input[type=checkbox],input[type=radio]{cursor:var(--cur-point),pointer}
/* text entry keeps the system I-beam: a custom arrow over a text field reads as broken */
input:not([type=checkbox]):not([type=radio]),textarea,[contenteditable]{cursor:text}
input[type=range]{cursor:var(--cur-point),pointer}
:disabled,.btn:disabled,[aria-disabled=true]{cursor:var(--cur-arrow),not-allowed}
/* pointer devices only: a touch screen has no cursor to style */
@media (hover:none){html,body{cursor:auto}}

/* Login · System tools drawer (2026-08-13)
   The test-mode and restore-point panels are real controls, but they are for whoever is running
   the trial, not for signing in. Folded behind one quiet line so the name picker is the page. */
.login-tools{margin-top:var(--sp-5);border-top:var(--stroke) solid var(--line-14);padding-top:var(--sp-3)}
.login-tools>summary{cursor:pointer;list-style:none;display:flex;align-items:baseline;gap:var(--sp-2);
  color:var(--grey-45);transition:color var(--t-micro) var(--ease)}
.login-tools>summary::-webkit-details-marker{display:none}
.login-tools>summary:hover{color:#fff}
.login-tools>summary .lt-t{font-family:var(--font-display);text-transform:uppercase;
  letter-spacing:.08em;font-size:var(--fs-2)}
.login-tools>summary .lt-t::before{content:"+ ";}
.login-tools[open]>summary .lt-t::before{content:"– ";}
.login-tools>summary .lt-sub{color:var(--grey-45)}
.login-tools[open]>summary{margin-bottom:var(--sp-2)}
/* inside the drawer the panels no longer need their own top margin */
.login-tools .fresh-test{margin-top:var(--sp-2)}

/* Admin · Dashboard greetings: one row per seat, name then the editable line */
.greet-book{display:flex;flex-direction:column}
.gb-row{display:grid;grid-template-columns:minmax(140px,1fr) minmax(200px,2fr) auto;gap:var(--sp-3);
  align-items:center;padding:var(--sp-2) 0;border-bottom:var(--stroke) solid var(--line-08)}
.gb-who{display:flex;flex-direction:column;gap:2px;min-width:0}
.gb-name{color:#fff;font-size:var(--fs-3)}
.gb-input{font-size:var(--fs-3)}
.gb-tag{white-space:nowrap;text-align:right;color:var(--grey-45)}
@media (max-width:640px){.gb-row{grid-template-columns:1fr auto}.gb-input{grid-column:1/-1}}

/* Login ROAD TRAILS (2026-08-19, user), replacing the code rain: lights running a street grid and
   turning at right angles. Sits between the EVOLV logo and the name picker. White at opacity on the
   navy, never a new hue, and it fades out at both ends so it reads as a band of the page rather than
   a pasted-in box. Decorative only, so it is aria-hidden and carries no layout weight. */
.trails{position:relative;flex:1 1 auto;min-height:120px;max-height:38vh;margin:var(--sp-4) 0;overflow:hidden;
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 18%,#000 82%,transparent),linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  -webkit-mask-composite:source-in;
  mask-image:linear-gradient(180deg,transparent,#000 18%,#000 82%,transparent),linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-composite:intersect}
.trail-canvas{display:block;width:100%;height:100%}
@media (max-width:900px){.trails{min-height:70px;max-height:22vh}}

/* An overbooked board-day: past the 14-slot cap, on the board rather than only in a confirm
   dialogue at booking time. Red is reserved for this, a state that is already wrong. */
.av-table tbody tr.st-row-sub td.av-over{background:var(--bad-12);color:var(--bad);font-weight:700}
.av-table tbody tr.av-over-row td.camp{color:var(--bad)}
.av-table tbody tr.av-over-row td.note{color:var(--bad)}

/* Has the deal followed the process: six ticks, no figure, same component in the card and the modal */
.ops-steps{display:flex;flex-wrap:wrap;gap:10px;margin-top:10px}
.ops-step{display:inline-flex;align-items:center;gap:6px;color:var(--grey-45);font-size:var(--fs-1);
  font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em}
.ops-tick{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;
  border:var(--stroke) solid var(--line-22);border-radius:3px;font-size:var(--fs-1);line-height:1}
.ops-step.done{color:#fff}
.ops-step.done .ops-tick{background:var(--hl-12);border-color:transparent;color:#fff}

/* The log dot: outstanding, done, or never needed doing */
.log-dot.done{background:transparent;border:var(--stroke) solid var(--line-40);box-shadow:none}

/* Items of interest: below what is waiting on you, and visibly not part of it */
.sig-head{display:flex;align-items:center;gap:var(--sp-2);margin:var(--sp-5) 0 var(--sp-2);
  text-transform:uppercase;letter-spacing:.06em;font-size:var(--fs-1);color:var(--grey-45)}
.sig-head::after{content:"";flex:1;height:var(--stroke);background:var(--line-08)}
.att.sig{border-left:2px solid var(--warn)}

/* A section caption with no title above it (2026-08-13, user): the sections lost their headings
   so the content leads, but the one line saying what the section is came back. Dashboard stays
   clean and has none. */
/* ===== one rhythm and one heading size for every page (2026-08-17, user) =====
   `.page-stack` is the body of a section. Its direct children are the page's SUBJECTS — the
   pipeline, the sheet, the availability board — and they get a full --sp-7 between them, because
   at 48px they read as one continuous wall of content.
   The block headings all sat at different sizes: Pipeline and the dashboard blocks on --fs-6,
   while "Sell Through" had NO size rule at all and was falling through to the browser's default
   h2. One token now, everywhere, so they cannot drift apart again. */
.page-stack > * + *{margin-top:var(--sp-7)}
.dash-block h2,.pipeline h2,.st h2,.out-head h2,.fin-card h2{
  font-size:var(--fs-8);text-transform:uppercase;letter-spacing:.02em}

/* EACH BLOCK IS ITS OWN CARD (2026-08-18, user). The dividers under the headings are gone again:
   the card edge carries the hierarchy, which is the CI's own way of separating things. The older
   rules stand — no rule above the page header, no separators BETWEEN blocks, and no new element
   for either, since this is the block's own border.
   The cards INSIDE a block (deals, tickets, chase cards) drop to a quieter border so a page never
   reads as two competing boxes. */
.dash-block,.pipeline,.outstanding,.fin-card,.coverage,.archive,.st{
  position:relative;border:var(--stroke) solid var(--line-22);
  border-radius:var(--notch) 0 var(--notch) 0;padding:var(--sp-4);
  /* THE CARDS ARE THE LIGHT, THE PAGE IS THE DARK (2026-08-19, user, swapping the 2026-08-18
     direction), and the contrast comes from the page being darker underneath (the --depth-* glow
     tints). Still no new hue.
     THE LIGHT SITS ON NAVY, NEVER ON BLACK. Two layers, deliberately, and they must not be merged:
     the highlight used to be a grey tint composited straight onto black, which lands on rgb(22,22,22)
     — a LITERALLY NEUTRAL grey, hard against a strongly blue field. Simultaneous contrast makes that
     read AMBER, which is exactly what it looked like on screen. Over the navy layer the same tint
     lands on rgb(40,52,73), blue-dominant, and the warm cast is gone. No palette value fixes this on
     its own: #E0E0DF has blue as its LOWEST channel, so it is the warmest neutral we have. */
  background:linear-gradient(180deg,rgba(224,224,223,.08),rgba(224,224,223,.015) 42%,transparent 70%),
    linear-gradient(180deg,rgba(18,40,76,.52),rgba(18,40,76,.32)),
    var(--black);
  box-shadow:0 1px 0 rgba(224,224,223,.04) inset,0 18px 40px -28px rgba(0,0,0,.9)}
/* the halftone the CI asks for: visible at rest on a card, never a flat outline */
.dash-block::before,.pipeline::before,.outstanding::before,
.fin-card::before,.coverage::before,.archive::before,.st::before{
  content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;opacity:.5;
  mix-blend-mode:screen;
  background:radial-gradient(rgba(224,224,223,.055) 22%,transparent 23%) 0 0/3px 3px}
.dash-block > *,.pipeline > *,.outstanding > *,.fin-card > *,
.coverage > *,.archive > *,.st > *{position:relative}
.dash-block > h2,.pipeline > h2,.st > h2,.fin-card > h2,
.out-head,.st-head,.pipe-head,.section-head{margin-bottom:var(--sp-3)}
.dash-block .deal,.outstanding .deal,.fin-card .deal,.coverage .cov-row,.archive .deal{
  border-color:var(--line-08)}
.dash-block .deal:hover,.outstanding .deal:hover,.fin-card .deal:hover{border-color:var(--line-22)}
/* the page header and the bare Sales row are not blocks: no card around either */
.page-stack > .section-head,.section-head.bare{border:none;padding:0;background:none}

/* ===================== operations =====================
   The strip runs whether or not anything is wrong, because "no board is overbooked" is worth
   saying too. Red here means the same as red everywhere in this build: a state that is already
   wrong, not a warning about one that might be. */
.ops-alert{display:flex;flex-direction:column;gap:var(--sp-2);padding:14px 16px;
  border:var(--stroke) solid rgba(232,124,124,.4);border-radius:var(--notch) 0 var(--notch) 0;
  background:rgba(232,124,124,.08)}
.ops-alert.clear{border-color:var(--line-14);background:rgba(255,255,255,.02)}
.ops-alert-t{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.04em;
  font-size:var(--fs-3);color:var(--bad)}
.ops-alert.clear .ops-alert-t{color:var(--grey-70)}
.ops-alert-list{display:flex;flex-wrap:wrap;gap:8px}
.ob-chip{display:inline-flex;align-items:center;gap:8px;cursor:pointer;padding:5px 11px;
  font-family:var(--font-display);font-size:var(--fs-2);text-transform:uppercase;letter-spacing:.05em;
  color:var(--bad);background:rgba(232,124,124,.12);border:var(--stroke) solid rgba(232,124,124,.45);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;transition:all var(--t-micro) var(--ease)}
.ob-chip:hover{background:rgba(232,124,124,.22);border-color:var(--bad)}
.ob-days{color:var(--grey-70)}
.ob-flag{margin-left:10px;font-family:var(--font-body);text-transform:none;letter-spacing:0;
  font-size:var(--fs-2);color:var(--bad)}

/* the flighting schedule: Sales Availability's own table, with the card's details on the row and
   no figures anywhere */
.fs-table td.fs-camp{min-width:250px;padding-top:9px;padding-bottom:9px}
.fs-camp .fs-name{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.fs-name{font-size:var(--fs-4);color:#fff}
.fs-camp .fs-sub{display:block;margin-top:3px;white-space:nowrap}
.fs-camp.clickable{cursor:pointer}
.fs-camp.clickable:hover .fs-name{color:var(--hl)}
.fs-live{font-family:var(--font-display);font-size:var(--fs-1);letter-spacing:.1em;
  color:var(--ok);background:var(--ok-12);border:var(--stroke) solid var(--ok);
  padding:2px 7px;border-radius:999px}
.fs-table tbody tr.fs-active td.camp{border-left:2px solid var(--ok)}
.fs-table td.av-over{background:var(--bad-12);color:var(--bad);font-weight:700}

/* where a campaign sits in the Operations pipeline */
.ops-stage.ops-artwork{background:var(--warn-12);color:var(--warn);border-color:transparent}
.ops-stage.ops-rejected,.ops-stage.ops-no_artwork{background:rgba(232,124,124,.14);color:var(--bad);border-color:transparent}
/* ===================== section icons =====================
   One line weight, one 24-box, currentColor: the CI's own monoline, the same as the board icon and
   the bell. An icon NEVER stands alone — it sits beside the words it belongs to. */
h2.has-icon,.arch-head{display:flex;align-items:center;gap:var(--sp-2)}
.sec-icon{display:inline-flex;flex:0 0 auto;width:1em;height:1em;color:var(--hl);opacity:.85}
/* AN ICON IS THE HEIGHT OF ITS HEADING (2026-08-19, user): the .82em override made it read as a
   smaller companion to the words rather than their equal. One em, same as everywhere else. */
.sec-icon svg{width:100%;height:100%;display:block;fill:none;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}
.arch-head .sec-icon{width:15px;height:15px;color:var(--grey-45)}
.arch-head:hover .sec-icon{color:var(--hl)}

/* how a campaign changes or ends: one door, the outcomes as cards (2026-08-18, user) */
.chg-list{display:flex;flex-direction:column;gap:var(--sp-2);margin-top:var(--sp-3)}
.chg-opt{display:flex;flex-direction:column;gap:4px;text-align:left;cursor:pointer;padding:14px 16px;
  background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;transition:all var(--t-micro) var(--ease)}
.chg-opt:hover{border-color:var(--line-40);background:rgba(255,255,255,.045)}
.chg-opt .chg-t{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.04em;
  font-size:var(--fs-3);color:#fff}
.chg-opt.off{opacity:.45;cursor:not-allowed}
.chg-opt.off:hover{border-color:var(--line-14);background:rgba(255,255,255,.02)}

/* a new creative on a campaign that is already on the boards: red, because it is live and unchecked */
.ops-stage.ops-recheck{background:rgba(232,124,124,.14);color:var(--bad);border-color:transparent;font-weight:700}
.ops-stage.ops-flighting{background:var(--info-12);color:var(--info);border-color:transparent}
.ops-stage.ops-pof,.ops-stage.ops-pof_sent{background:var(--ok-12);color:var(--ok);border-color:transparent}

/* site health */
.ticket{border-left:2px solid var(--line-22)}
.ticket.sev-dark{border-left-color:var(--bad)}
.ticket.sev-faulty{border-left-color:var(--warn)}
.ticket.sev-minor{border-left-color:var(--line-40)}
.ticket.done{opacity:.62}
.ticket-body{margin-top:12px;padding-top:12px;border-top:var(--stroke) solid var(--line-08);
  display:flex;flex-direction:column;gap:10px}
.ticket-impact{color:var(--warn)}
.pof-list{display:flex;flex-direction:column;gap:6px;margin-top:8px}
/* centred since the row leads with a thumb (2026-09-18); the modal's rows share the class and
   sit just as well on the centre line */
.pof-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
/* the run choice is one or the other, so it is radio buttons (2026-09-16, user), drawn as
   selectable cards (2026-09-18, user): the generic .field rules were swallowing the native
   layout, so the option owns its own card and the input stays real but hidden. */
.radio-row{display:flex;gap:10px;flex-wrap:wrap}
.field .radio-opt{position:relative;flex:1 1 220px;display:flex;align-items:flex-start;gap:12px;
  margin:0;padding:13px 15px;background:rgba(255,255,255,.012);
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  text-transform:none;letter-spacing:0;cursor:var(--cur-point),pointer;
  transition:border-color .3s var(--ease),background .3s var(--ease)}
.field .radio-opt:hover{border-color:var(--line-22)}
.field .radio-opt:has(input:checked){border-color:var(--hl);background:var(--hl-12)}
.field .radio-opt:has(input:checked) .cap{color:var(--hl)}
.field .radio-opt input{position:absolute;width:1px;height:1px;padding:0;margin:0;opacity:0;
  pointer-events:none}
.radio-dot{flex:0 0 auto;width:16px;height:16px;margin-top:2px;border-radius:50%;
  border:var(--stroke) solid var(--grey-45);position:relative;
  transition:border-color .3s var(--ease)}
.radio-dot::after{content:'';position:absolute;inset:3px;border-radius:50%;background:var(--hl);
  transform:scale(0);transition:transform .25s var(--ease)}
.radio-opt input:checked ~ .radio-dot{border-color:var(--hl)}
.radio-opt input:checked ~ .radio-dot::after{transform:scale(1)}
.radio-opt input:focus-visible ~ .radio-dot{box-shadow:0 0 0 3px var(--hl-12)}
.radio-txt{display:flex;flex-direction:column;gap:3px;min-width:0}
.radio-opt .radio-l{color:#fff;font-size:var(--fs-4)}
.pof-name{font-size:var(--fs-4);color:#fff;overflow-wrap:anywhere}

/* a creative's own Operations decision, shown on the deal's document list */
.doc-check{font-size:var(--fs-2);letter-spacing:.02em;margin-top:5px;color:var(--grey-45)}
.doc-check.ok{color:var(--ok)}
.doc-check.bad{color:var(--bad)}
.doc-check.pending{color:var(--warn)}
.doc-slot.creative{margin-left:var(--sp-3)}
.doc-slot.creative-head .doc-slot-meta{color:var(--grey-45)}

/* the rep's own proof-of-flighting work, on the Sales page */
.proof-work .pw-group{margin-top:var(--sp-4)}
.pw-head{display:flex;align-items:baseline;gap:10px;margin-bottom:6px}
.pw-head .pw-t{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.05em;font-size:var(--fs-3);color:var(--hl)}
.pw-head .count{color:var(--grey-45);font-size:var(--fs-2)}
.pw-row{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;padding:14px 16px;margin-top:10px}
.pw-row .pw-main{flex:1 1 240px;min-width:0}
.pw-row .pw-name{color:#fff;font-size:var(--fs-3)}
.pw-row .pw-acts{display:flex;gap:10px;align-items:center;flex-wrap:wrap}

/* a seat's own numbers: won against lost, the pipeline, revenue against target */
.scorecard .sc-head{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-bottom:var(--sp-2)}
/* the fold control sits inside the head beside the date pickers, so it cannot claim the full row a
   standalone block toggle does (2026-08-26). IT STILL TAKES EVERY PIXEL THE PICKERS DO NOT
   (2026-08-31, user): `width:auto` shrank it to the width of two words and a caret, which is the
   hard-to-hit target he means. It grows instead, so the whole empty stretch left of the pickers
   opens the card and the pickers stay their own controls. */
.scorecard .sc-head .block-toggle{width:auto;flex:1 1 auto;margin-bottom:0;align-items:baseline}
.scorecard .sc-head .spacer{flex:1 1 auto}
.sc-picker{margin:0}
.sc-picker .field{min-width:150px}
.sc-card{padding:var(--sp-3);margin-top:var(--sp-3)}
.sc-card-h{display:flex;align-items:baseline;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-bottom:6px}
.sc-card-t{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.05em;font-size:var(--fs-3);color:var(--hl)}
.hint2{margin-bottom:var(--sp-2)}
.sc-figs{display:flex;gap:var(--sp-4);flex-wrap:wrap;margin:var(--sp-2) 0}
.sc-fig{min-width:180px}
.sc-fig-l{font-size:var(--fs-2);letter-spacing:.08em;text-transform:uppercase;color:var(--grey-45);margin-bottom:4px}
.sc-fig-v{font-family:var(--font-display);font-size:var(--fs-6);color:#fff;line-height:1.1}
.sc-fig.ok .sc-fig-v{color:var(--ok)}
.sc-fig.warn .sc-fig-v{color:var(--warn)}
/* a figure that is also a door: the desk blocks' counts (2026-09-16) */
button.sc-fig.linkfig{background:none;border:0;padding:0;text-align:left;cursor:pointer;font:inherit;color:inherit}
button.sc-fig.linkfig:hover .sc-fig-l{color:var(--hl)}
/* the Operations movement rows: a date, a campaign, its boards */
.ops-mv{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;width:100%;background:none;border:0;padding:6px 0;text-align:left;cursor:pointer;font:inherit;color:inherit}
.ops-mv-n{color:#fff}
.ops-mv:hover .ops-mv-n{color:var(--hl)}
.sc-sub + .ops-mv{margin-top:2px}
.sc-bar{display:flex;height:10px;border-radius:3px;overflow:hidden;background:var(--grey-22);margin-top:8px}
.sc-bar.empty{opacity:.4}
.sc-bar-won{background:var(--ok)}
.sc-bar-lost{background:var(--bad)}
.sc-key{display:flex;gap:18px;margin-top:8px;color:var(--grey-45);font-size:var(--fs-2)}
.sc-k{display:inline-flex;align-items:center;gap:7px}
.sc-k i{width:12px;height:12px;border-radius:3px;display:inline-block}
.sc-k.won i{background:var(--ok)}
.sc-k.lost i{background:var(--bad)}
.sc-counts{display:flex;gap:var(--sp-4);flex-wrap:wrap;margin:var(--sp-2) 0 var(--sp-3)}
.sc-count{min-width:110px}
.sc-count-v{font-family:var(--font-display);font-size:var(--fs-5);color:#fff;line-height:1.1}
.sc-two{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4)}
@media (max-width:900px){.sc-two{grid-template-columns:1fr}}
.sc-sub{font-size:var(--fs-2);letter-spacing:.08em;text-transform:uppercase;color:var(--grey-45);margin-bottom:6px}

/* the activity feed is paged: what is on screen, and the way to ask for more */
.act-foot{display:flex;align-items:center;gap:16px;flex-wrap:wrap;padding:16px 6px 2px;border-top:var(--stroke) solid var(--line-08);margin-top:8px}
.act-foot:empty{display:none;border-top:0;padding:0;margin:0}

/* ---------- Site development (the MD's section) ---------- */
.field-row{display:flex;gap:14px;flex-wrap:wrap}
.field-row>.field{flex:1 1 180px;min-width:0}
.sd-badge{display:inline-flex;align-items:center;padding:3px 10px;white-space:nowrap;
  border:var(--stroke) solid var(--line-22);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  font-family:var(--font-display);text-transform:uppercase;letter-spacing:.05em;font-size:var(--fs-1)}
.sd-badge.ok{border-color:var(--ok);color:var(--ok)}
.sd-badge.warn{border-color:var(--warn);color:var(--warn)}
.sd-badge.bad{border-color:var(--bad);color:var(--bad)}
.sd-card{display:flex;flex-direction:column;gap:6px}
.sd-card-h{display:flex;align-items:baseline;gap:12px;justify-content:space-between;flex-wrap:wrap}
.sd-name{color:#fff;font-size:var(--fs-4)}
.sd-bits{color:var(--grey-45)}
.sd-lost{color:var(--bad)}
.sd-acts{display:flex;gap:10px;flex-wrap:wrap;margin-top:var(--sp-2)}
.sd-files{display:flex;flex-direction:column;gap:2px;margin:10px 0}
/* TWO DIFFERENT THINGS ARE CALLED `.sd-step` AND THEY WERE FIGHTING (2026-08-31, user: "formatting
   still a mess on less wide screens"). This one is the TOWN PLANNER's four steps, a dot beside a
   label; the other is the Developments stage strip, a stacked tab. Neither was scoped, so the
   stage tab inherited `display:flex` from here and laid its number, its label and its sub-label out
   in a ROW — which overlapped the tab beside it the moment the screen was not very wide. Both are
   scoped to their own container now, so the names can never reach across again.
   The same trap as "never name an inner grid after its section" (2026-08-27), one layer out: it is
   not the section it collides with, it is the OTHER component that picked the same word. */
.sd-steps{display:flex;gap:var(--sp-3);flex-wrap:wrap;margin:12px 0}
.sd-steps .sd-step{display:flex;gap:10px;align-items:flex-start;min-width:150px}
.sd-steps .sd-step-dot{width:10px;height:10px;border-radius:50%;margin-top:5px;flex:0 0 auto;
  border:var(--stroke) solid var(--line-40);background:transparent}
.sd-steps .sd-step.done .sd-step-dot{background:var(--ok);border-color:var(--ok)}
.sd-steps .sd-step.now .sd-step-dot{background:var(--warn);border-color:var(--warn)}
.sd-steps .sd-step-l{color:var(--grey);font-size:var(--fs-3)}
.sd-steps .sd-step.done .sd-step-l{color:#fff}
/* SEARCH AND NARROW (2026-08-27, user: hundreds of landlords at once). One row above the list. */
.ll-tools{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:var(--sp-3) 0 var(--sp-2)}
.ll-tools .act-search{flex:1 1 260px}
.ll-tools .sel{width:auto;min-width:170px;padding:9px 11px;font-size:var(--fs-2)}
.ll-card{padding:0;overflow:hidden;margin-top:12px}
.ll-head{display:flex;align-items:baseline;gap:14px;width:100%;padding:16px 20px;cursor:pointer;
  background:none;border:0;color:inherit;text-align:left;font:inherit;flex-wrap:wrap}
.ll-head .tw{transition:transform var(--t-micro) var(--ease);color:var(--grey-45)}
.ll-head.open .tw{transform:rotate(90deg)}
.ll-name{color:#fff;font-family:var(--font-display);text-transform:uppercase;
  font-size:var(--fs-6);letter-spacing:var(--ls-btn);line-height:1.15}
/* THE NAME LEADS, THE CONTACT LINE FOLLOWS IT (2026-08-27, user). The head used to be four things at
   one weight, so a landlord card read as a row of text rather than as a named thing with detail
   under it. Moderniz on the name, the rest dropped back and put on its own line. */
.ll-head{align-items:center;row-gap:2px}
.ll-head .ll-name{flex:1 1 auto;order:1}
.ll-head .ll-counts{order:2}
.ll-head>.cap:not(.ll-counts){order:3;flex:1 1 100%;padding-left:26px;color:var(--grey-45)}
.ll-head .spacer{display:none}
/* THE COUNTS LINE WRAPS (2026-09-27, user). It was nowrap inside a card that clips
   (`.ll-card` is `overflow:hidden`), so on a phone the tail — the counts and the date — was
   cut off with nothing saying so. A line that wraps is still information; a line that clips
   is data loss. Declared rather than defaulted so the resp: pin has something to hold. */
.ll-counts{white-space:normal}
.ll-box{padding:0 20px 16px}
.ll-box.shut{display:none}
.ll-row{display:flex;align-items:center;gap:14px;padding:10px 0;cursor:pointer;flex-wrap:wrap;
  border-top:var(--stroke) solid var(--line-08)}
.ll-row:hover .ll-prop{color:#fff}
.ll-prop{color:var(--grey)}
/* THE ROW CAN BE WORKED FROM, NOT ONLY READ (2026-08-26, user). "On the register" and "Stopped" sit
   where the move button sits, so a finished development reads as finished rather than as a row that
   lost its button. */
.ll-done{color:var(--grey-45);white-space:nowrap}
.ll-acts{display:flex;gap:10px;margin-top:14px;flex-wrap:wrap}
/* A PROPERTY AND ITS PROPOSALS (2026-08-27, user: the landlord is the bucket, "under landlords row
   or card i would like the proposals and drafts to be visible from there"). The property row
   carries the stage and the next move; its proposals sit under it, indented, the live one first
   and the superseded ones folded behind a link and dimmed when shown. */
/* EACH PROPOSAL IS ITS OWN CARD (2026-09-01, user). It was a hairline between rows, so several
   properties read as one long list. The EDGE is what carries it, softened to `--line-08` so the
   card inside the landlord's card does not compete with it: the outer edge keeps the hierarchy,
   which is this build's rule for a card within a card. No new tinted surface is introduced, so the
   `vis:` composite check still governs every fill on the page. */
.ll-prop-block{border-top:0;margin-top:10px;padding:12px 14px}
.ll-prop-block.card{border-color:var(--line-08)}
.ll-prop-block:first-child{margin-top:0}
.ll-prop-block .ll-row{border-top:0;padding-top:0;padding-bottom:4px}
.ll-prs{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:0 0 0 20px}
.ll-pr{display:flex;align-items:center;gap:12px;flex-wrap:wrap;width:100%;padding:5px 0}
.ll-pr.was{opacity:.6}
.ll-pr-n{color:#fff;white-space:nowrap}
.chip.pr-sent{background:rgba(255,255,255,.06);color:#fff;border-color:var(--line-40)}
.chip.pr-saved{background:var(--hl-12);color:var(--hl);border-color:transparent}
.chip.pr-draft{background:rgba(240,180,80,.12);color:var(--warn);border-color:transparent}
.ll-rename{margin-top:4px}
.ll-sends{width:100%;padding-left:16px;border-left:var(--stroke) solid var(--line-08);margin-top:6px}
.ll-sends .ll-pr{opacity:.72}
.ll-none{padding:4px 0 12px}

/* ===================== the proposal, as a screen (2026-08-27, user) =====================
   "the layout to flow of entering info and presenting" did not work, because the tool's inputs sat
   inside the document the landlord reads. This is the entering half, in E.V.O.S.'s own language:
   six steps in the order a proposal is actually built, the figure it comes to pinned where it can
   be watched while the numbers are typed, and what is still missing said out loud rather than only
   when Present is pressed. */
.prop-screen{display:flex;flex-direction:column;gap:var(--sp-4)}
.prop-head{display:flex;align-items:flex-end;gap:var(--sp-4);flex-wrap:wrap;padding:var(--sp-4)}
.prop-head-l h2{font-size:var(--fs-8);color:#fff}
.prop-head-r{margin-left:auto;text-align:right}
.prop-head-n{font-family:var(--font-display);font-size:var(--fs-8);color:#fff;line-height:1.1}

/* the steps are wayfinding AND the way through, so they carry their number and their words */
.prop-steps{display:flex;gap:10px;flex-wrap:wrap}
.prop-step{display:flex;align-items:center;gap:9px;padding:10px 15px;cursor:pointer;
  background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:var(--grey-70);
  font-family:var(--font-body);font-size:var(--fs-3);
  transition:border-color var(--t-micro) var(--ease),color var(--t-micro) var(--ease)}
.prop-step:hover{color:#fff;border-color:var(--line-40)}
.prop-step.on{color:#fff;border-color:var(--hl)}
.prop-step-n{font-family:var(--font-display);font-size:var(--fs-2);color:var(--grey-45)}
.prop-step.on .prop-step-n{color:var(--hl)}

.prop-body{display:flex;flex-direction:column;gap:var(--sp-4)}
.prop-card{padding:var(--sp-4)}
.prop-card h3{font-size:var(--fs-6);color:#fff;margin-bottom:var(--sp-2)}
.prop-card .field:last-child{margin-bottom:0}
.prop-card .field-row .field{flex:1 1 180px}

/* what is still missing, live, in the tool's own words */
.prop-miss{padding:var(--sp-3) var(--sp-4);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.02)}
.prop-miss-i{color:var(--warn)}

.prop-foot{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding-top:var(--sp-2)}

/* pictures: what is there, and the two things you can do to it */
.prop-pics{display:flex;gap:var(--sp-4);flex-wrap:wrap}
.prop-pic{flex:1 1 260px;display:flex;flex-direction:column;gap:9px}
/* THE WHOLE PICTURE, AS IT WAS UPLOADED (2026-08-27, user): it may be scaled, never cropped and
   never squashed. A mockup that arrives 21:9 or a map that arrives square is shown as it is, so
   what somebody checks here is the picture they actually have. */
.prop-pic-img{width:100%;height:auto;max-height:460px;object-fit:contain;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;border:var(--stroke) solid var(--line-14)}
.prop-pic-none{padding:var(--sp-4);text-align:center;border:var(--stroke) dashed var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.prop-pic-acts{display:flex;gap:10px;flex-wrap:wrap}
/* the mark size sliders on tab 2 (2026-09-11, user) */
.prop-mk-row{display:flex;align-items:center;gap:12px}
.prop-mk-row input[type=range]{flex:1 1 auto;max-width:300px;accent-color:var(--hl)}
.prop-mk-v{min-width:44px}
.prop-gal{display:flex;gap:var(--sp-3);flex-wrap:wrap;align-items:flex-start}
.prop-gal-i{width:200px;display:flex;flex-direction:column;gap:7px}
/* FOUR WIDE, THREE HIGH (2026-08-27, user). Fixed by ratio rather than by height, so the nine read
   as one set at any column width, and the same crop appears on the summary. */
.prop-gal-i img{width:100%;aspect-ratio:4/3;height:auto;object-fit:cover;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;border:var(--stroke) solid var(--line-14)}
.prop-gal-i.empty-slot{aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;
  text-align:center;padding:var(--sp-3);border:var(--stroke) dashed var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:var(--grey-45)}
.prop-gal-i input{width:100%;padding:8px 10px;background:rgba(255,255,255,.02);
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  color:#fff;font-family:var(--font-body);font-size:var(--fs-2);outline:none}

/* the cost lines and the scenarios are lists that grow, so they read as rows rather than fields */
.prop-opex{display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.prop-opex-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;width:100%}
.prop-opex-row input{padding:9px 11px;background:rgba(255,255,255,.02);
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  color:#fff;font-family:var(--font-body);font-size:var(--fs-3);outline:none;width:130px}
.prop-opex-row input:focus,.prop-gal-i input:focus{border-color:var(--hl)}
.prop-opex-row .sel{width:150px}
.prop-scen{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.prop-scen-i{display:inline-flex;align-items:center;gap:8px}
.prop-scen-add{width:90px;padding:9px 11px;background:rgba(255,255,255,.02);
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  color:#fff;font-family:var(--font-body);font-size:var(--fs-3);outline:none}
/* A DIVIDER BELONGS BETWEEN TWO ROWS, SO IT IS DECLARED ON THE PAIR (2026-09-03, user, from a
   screenshot of two lines stacked under a Developments stage heading). Every one of these was
   written as "a border on each row, removed from the first by :first-of-type", and
   `:first-of-type` means the first element of that TAG among its siblings, not the first one
   carrying the class. A heading div sits above these rows, so the guard matched the HEADING and no
   row ever lost its border: the head's border-bottom and the first row's border-top drew one on top
   of the other. Written as an adjacency it cannot come back, whatever gets put above the rows. */
.prop-opt{padding:var(--sp-3) 0}
.prop-opt + .prop-opt{border-top:var(--stroke) solid var(--line-08)}
.tickline{display:flex;align-items:center;gap:10px;color:#fff;font-size:var(--fs-4);cursor:pointer;
  margin-bottom:var(--sp-2)}
.tickline input{width:16px;height:16px;accent-color:var(--hl)}
.prop-out-acts{display:flex;gap:12px;flex-wrap:wrap;margin:var(--sp-3) 0}
.prop-leave-acts{margin-top:var(--sp-3)}
/* THE SUMMARY (2026-08-27, the director). It is the cover, so it leads on the display line and the
   company tagline, carries one figure, and shows nine sites already running. Nine is a 3x3 on a
   wide screen and reflows down; a slot with no picture yet says where to add one rather than
   leaving a hole. */
.prop-sum-hero{padding:var(--sp-5) var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-3)}
.prop-sum-tag{color:var(--grey-70);font-size:var(--fs-5);max-width:46ch}
.prop-sum-lead{max-width:78ch}
.prop-sum-figure{margin-top:var(--sp-3)}
.prop-sum-n{font-family:var(--font-display);font-size:var(--fs-8);color:#fff;line-height:1.1;margin:4px 0}
/* the cover's own picture strip, which replaced the three numbered lines */
.pdoc-info{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-3)}
.pdoc-info .pdoc-fig img{height:120px}
/* WHY A DIGITAL ASSET (2026-08-27, reworked three times at the user's instruction). ONE CARD PER
   POINT, with no wrapper card around them, and THE ICON IS THE FOCUS of each: it sits large above
   the words rather than beside them. The text is borderless until touched, so a card reads as the
   copy it becomes. There is no way to add a point here, by instruction. */
.why-sec{margin-top:var(--sp-5)}
.why-sec:first-child{margin-top:0}
.why-sec h3{font-size:var(--fs-6);color:#fff;margin-bottom:6px}
/* THREE ACROSS, TWO DOWN (2026-08-27, user). Auto-fitting to the window put six in a row on a wide
   screen and the titles were being chopped off inside their own fields. Six points is a fixed
   number, so the grid is a fixed number too. */
.why-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-3);
  margin-top:var(--sp-3)}
@media (max-width:1150px){ .why-grid{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (max-width:720px){ .why-grid{grid-template-columns:1fr} }
.why-card{padding:var(--sp-4);display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.why-ico{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  background:rgba(255,255,255,.03)}
.why-ico .sec-icon{width:22px;height:22px;opacity:1}
.why-t{width:100%;background:none;border:var(--stroke) solid transparent;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;padding:4px 6px;margin:0 -6px;
  color:#fff;font-family:var(--font-display);text-transform:uppercase;font-size:var(--fs-3);
  letter-spacing:var(--ls-btn);outline:none}
.why-b{width:100%;background:none;border:var(--stroke) solid transparent;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;padding:4px 6px;margin:0 -6px;
  color:var(--grey-70);font-family:var(--font-body);font-size:var(--fs-3);line-height:1.6;
  min-height:110px;resize:vertical;outline:none}
.why-t:hover,.why-b:hover,.why-cap:hover{border-color:var(--line-14)}
.why-t:focus,.why-b:focus{border-color:var(--hl)}

/* THE PROJECTS CAROUSEL (2026-08-27, user): three at a time, large enough to judge, each with a
   tick that decides whether it goes into the proposal, and a click that opens it full size. */
.why-pics-card{padding:var(--sp-4);margin-top:var(--sp-3)}
/* A TOUCH SMALLER, SO THE THREE BREATHE (2026-08-27, user). With the tile frames gone the pictures
   were sitting shoulder to shoulder; the gap between them widens and each one gives a little back
   rather than the card getting bigger. */
.why-strip{display:flex;align-items:center;gap:var(--sp-3);--why-gap:26px}
.why-arrow{flex:0 0 auto}
.why-arrow:disabled{opacity:.25;cursor:default}
/* THE TRACK SLIDES INSIDE THE VIEW. Three are visible; the rest are there all along, off to the
   side, so moving through the library is a movement rather than a rebuild. */
.why-view{flex:1 1 auto;min-width:0;overflow:hidden}
.why-track{display:flex;gap:var(--why-gap);
  transition:transform .45s var(--ease);will-change:transform}
/* NO FRAME ON THE THREE TILES (2026-08-27, user): the card around them is the frame, and a border
   inside a border reads as a box in a box. What a tile still says is whether it is IN the proposal,
   and it says it with the picture's own strength and its tick rather than with an outline. */
.why-pic{flex:0 0 calc((100% - (2 * var(--why-gap))) / 3);
  position:relative;display:flex;flex-direction:column;gap:9px;margin:0;min-width:0}
.why-pic .why-shot{width:94%;margin:0 auto}
.why-shot{display:block;padding:0;border:0;background:none;cursor:zoom-in;width:100%}
.why-pic img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.why-pic:not(.on) img{opacity:.45}
/* REPLACE AND REMOVE ARE ALWAYS THERE (2026-08-27, user), under the picture beside its tick,
   rather than an overlay that only appears when a mouse happens to pass over it. */
.why-pic-acts{display:flex;gap:14px;align-items:center}
.why-cap{background:none;border:var(--stroke) solid transparent;padding:3px 5px;margin:0 -5px;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:var(--grey-45);
  font-family:var(--font-body);font-size:var(--fs-2);outline:none;width:100%;min-width:0}
.why-cap:focus{border-color:var(--hl);color:#fff}
.why-use{display:flex;align-items:center;gap:9px;cursor:pointer;margin-top:2px}
.why-use input{width:15px;height:15px;accent-color:var(--hl)}
.why-foot{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:var(--sp-3)}
.why-stamp{margin-top:var(--sp-2)}

/* full size, because that is the size it will be judged at */
.why-lightbox{align-items:center;justify-content:center;padding:var(--pad-x);cursor:zoom-out}
.why-lb{max-width:1100px;width:100%;display:flex;flex-direction:column;gap:var(--sp-3);cursor:default}
.why-lb img{width:100%;max-height:76vh;object-fit:contain;
  border-radius:var(--notch) 0 var(--notch) 0;border:var(--stroke) solid var(--line-14)}
.why-lb-foot{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
@media (prefers-reduced-motion:reduce){ .why-track{transition:none} }
.prop-print-choices{display:flex;flex-direction:column;gap:10px}

/* ===================== the landlord's document, and the deck (2026-08-27) =====================
   Step 4 of plans/007: what the proposal PRODUCES, in E.V.O.S.'s own language. It is a document,
   not a section, so it takes the full width and keeps its own rhythm. No inputs live in here. */
.pdoc-wrap{display:flex;flex-direction:column;gap:var(--sp-4)}
.pdoc-bar{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.pdoc{display:flex;flex-direction:column;gap:var(--sp-7)}
.pdoc-sec{display:flex;flex-direction:column;gap:var(--sp-4)}
.pdoc-head h2{font-size:var(--fs-8);color:#fff}
.pdoc-head .cap{margin-top:6px;max-width:78ch}

/* THE COVER FILLS ITS SHEET SO ITS LOCKUP CAN SIT AT THE FOOT (2026-09-01, user: "move the logos
   to the bottom of the first page"). Pushed there by the layout, with `margin-top:auto`, rather
   than positioned there: an absolutely positioned mark takes no space, and the page above it would
   then have nothing telling it to keep clear.
   NOTHING MAY SHRINK. Making the sheet a column is what lets the page stretch, and a flex item
   shrinks by default: a page with too much on it would be squashed to fit and the builder's
   overflow warning, which asks whether the content is taller than the sheet, could never fire
   again. It was dead once before for exactly this reason, so every child is `flex-shrink:0`. */
.pp-sheet>*{flex:0 0 auto}
.pp-sheet>.pdoc{flex:1 0 auto}
.pdoc-cover{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:var(--sp-6)}
.pdoc-cover>.pdoc-lockup{margin-top:var(--sp-3)}

/* ---------- the title page (2026-09-09, user; reworked bigger the same day from his render:
   "the subheading should not say landlord proposal tool, it should say Landlord Site Proposal,
   both the title, sub title and tagline need to be bigger") ---------- */
.pdoc-title{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:var(--sp-5)}
.pdoc-title-top{display:flex;flex-direction:column;gap:var(--sp-3)}
.pdoc-title-name{font-size:52pt;line-height:1.02}
.pp-sheet.paper .pdoc-title-sub{font-family:var(--font-display);text-transform:uppercase;
  letter-spacing:var(--ls-btn);font-size:17pt;color:#10172B;margin-top:0}
.pp-sheet.paper .pdoc-title-tag{font-size:14.5pt;color:rgba(16,23,43,.75);text-transform:none;letter-spacing:0}
/* the person it is prepared for (2026-09-11, user): the third line of the title */
.pp-sheet.paper .pdoc-title-who{font-size:13pt;color:rgba(16,23,43,.78);
  text-transform:none;letter-spacing:0}
.pdoc-title-mark{flex:1 1 auto;min-height:0;display:flex;align-items:center;justify-content:center;
  border:var(--stroke) solid rgba(16,23,43,.16);border-radius:var(--notch) 0 var(--notch) 0;
  padding:var(--sp-5)}
/* the title page's mark is fixed (2026-09-11, user): the sliders never reach this plate */
.pdoc-title-logo{height:380px;max-height:100%;width:auto;max-width:80%;object-fit:contain}
.pdoc-title-row{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-4)}
.pdoc-title-chip{display:flex;align-items:center;gap:12px;padding:16px 18px;
  border:var(--stroke) solid rgba(16,23,43,.14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pdoc-title-chip .cap{font-size:11pt}

.pdoc-hero{display:flex;gap:var(--sp-6);flex-wrap:wrap;align-items:flex-start;
  padding-bottom:var(--sp-5);border-bottom:var(--stroke) solid var(--line-08)}
.pdoc-hero-l{flex:1 1 420px}
.pdoc-display{font-family:var(--font-display);text-transform:uppercase;font-size:var(--fs-display);
  line-height:1;color:#fff;letter-spacing:var(--ls-display)}
.pdoc-sub{color:var(--grey-70);font-size:var(--fs-5);margin-top:var(--sp-2)}
.pdoc-lead{color:var(--grey-70);font-size:var(--fs-4);max-width:56ch;margin-top:var(--sp-3);line-height:1.6}
.pdoc-lead strong{color:#fff}
.pdoc-headline{margin-top:var(--sp-4)}
.pdoc-headline-v{font-family:var(--font-display);font-size:var(--fs-8);color:#fff;line-height:1.1;margin:4px 0}
.pdoc-for{margin-top:var(--sp-3)}
.pdoc-info{flex:1 1 300px;display:flex;flex-direction:column;gap:var(--sp-3)}
.pdoc-info-step{display:flex;gap:14px;align-items:flex-start}
.pdoc-info-n{font-family:var(--font-display);font-size:var(--fs-6);color:var(--grey-45);line-height:1}
.pdoc-info-t{display:block;color:#fff;font-size:var(--fs-4)}

.pdoc-grid-2{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--sp-4)}
.pdoc-grid-3{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--sp-4)}
.pdoc-card{padding:var(--sp-4);display:flex;flex-direction:column;gap:10px}
.pdoc-card h3{font-size:var(--fs-6);color:#fff}
.pdoc-card p{line-height:1.65;max-width:78ch}
.pdoc-modelled strong{color:#fff}
.pdoc-principle-h{display:flex;align-items:baseline;gap:12px}
/* the principle cards sit tighter on paper (2026-09-09): these are the two pages that were
   running into the footer band in his example export */
.pp-sheet .pdoc-principle{padding:var(--sp-3) var(--sp-4)}
.pp-sheet .pdoc-principle .pdoc-p{line-height:1.55}
.pp-sheet .pdoc-sec .pdoc-modelled{margin:0}
.pdoc-principle-n{font-family:var(--font-display);font-size:var(--fs-5);color:var(--grey-45)}
.pdoc-formula{padding:var(--sp-2) var(--sp-3);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:#fff;font-size:var(--fs-3);
  background:rgba(255,255,255,.02);margin:var(--sp-2) 0}
.pdoc-tiles{display:flex;gap:var(--sp-3);flex-wrap:wrap;margin:var(--sp-2) 0}
.pdoc-tile{flex:1 1 180px;padding:var(--sp-3);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.02);
  display:flex;flex-direction:column;gap:6px}
.pdoc-tile-v{font-family:var(--font-display);font-size:var(--fs-6);color:#fff;line-height:1.1}
.pdoc-tile.big .pdoc-tile-v{font-size:var(--fs-8)}
.pdoc-row{display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  padding:9px 0}
.pdoc-row + .pdoc-row{border-top:var(--stroke) solid var(--line-08)}
.pdoc-row-v{color:#fff;font-size:var(--fs-4);text-align:right}
.pdoc-context{max-width:78ch;line-height:1.65}

.pdoc-tbl-wrap{overflow-x:auto}
.pdoc-tbl{width:100%;border-collapse:collapse;font-size:var(--fs-3)}
.pdoc-tbl th{text-align:left;font-size:var(--fs-2);letter-spacing:.1em;text-transform:uppercase;
  color:var(--grey-45);padding:9px 12px;border-bottom:var(--stroke) solid var(--line-14);white-space:nowrap}
.pdoc-tbl td{padding:10px 12px;border-bottom:var(--stroke) solid var(--line-08);color:var(--grey-70)}
.pdoc-tbl td:first-child{color:#fff}
.pdoc-tbl .num{text-align:right;font-variant-numeric:tabular-nums}

.pdoc-projects{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--sp-3)}
.pdoc-pics{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:var(--sp-4)}
.pdoc-fig{display:flex;flex-direction:column;gap:8px}
/* THE PICTURES RUN THE SAME MEASURE AS THE DIVIDER LINES (2026-09-09, user). The inset he saw was
   the browser's DEFAULT figure margin (1em 40px), never reset on the printed sheet. */
.pp-sheet .pdoc-fig{margin:0}
.pdoc-fig img{width:100%;height:180px;object-fit:cover;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;border:var(--stroke) solid var(--line-14)}
.pdoc-fig.wide img{height:300px}
.pdoc-opt .chip{align-self:flex-start}

/* ---- PRESENTING: THE ROOM, NOT THE PAPER (2026-08-27, user) ----
   E.V.O.S.'s own dark ground, at the size a room needs, and it moves. The white pages are for the
   thing that gets printed. Full screen is asked of the browser through the one mechanism the top
   bar's toggle uses, so a later global toggle cannot fight this one. */
.pdeck{position:fixed;inset:0;z-index:120;background:var(--black);display:flex;flex-direction:column;
  padding:var(--sp-4) var(--pad-x);overflow:hidden}
body.deck-open{overflow:hidden}
/* the ambient EVOLV wash, slowly drifting, so a held slide is never a flat rectangle */
.pdeck-glow{position:absolute;inset:-20%;pointer-events:none;z-index:0;
  background:
    radial-gradient(46% 38% at 18% 22%, rgba(18,40,76,.55), transparent 70%),
    radial-gradient(40% 34% at 82% 74%, rgba(18,40,76,.42), transparent 70%);
  animation:deckDrift 26s var(--ease) infinite alternate}
@keyframes deckDrift{ from{transform:translate3d(-2%,-1%,0) scale(1)} to{transform:translate3d(2%,1%,0) scale(1.06)} }
.pdeck-bar{position:relative;z-index:2;display:flex;align-items:center;gap:10px}
.pdeck-count{margin-left:6px}
/* THE STAGE MUST NOT CROP THE SLIDE (2026-08-27, user). It was hidden so the outgoing slide could
   travel out of frame, which also meant a tall slide had its lowest cards cut off. It scrolls
   instead, and the travelling slides are clipped by the deck itself. */
/* A PRESENTATION SLIDE IS SCALED TO FIT, IT IS NEVER SCROLLED (2026-08-31, user: "make sure that
   the whole size scales down preserving format"). This was `overflow:auto`, so on a laptop — where
   the type is at its maximum on WIDTH while the HEIGHT is short — a slide that did not fit grew a
   scrollbar, which is the presentation equivalent of running off the page. It is clipped now and
   nothing ever reaches the clip, because `propFitSlide` measures the slide and scales it. */
/* THE SLIDE IS CENTRED ON THE STAGE, NOT ALIGNED INSIDE A TRACK (2026-08-31, user: present mode
   "pushes the content too far right"). This was a grid with `place-items:center`, which centres an
   item INSIDE ITS GRID AREA — and an implicit `auto` track GROWS to fit an item bigger than the
   container. The slide is a fixed 1500px canvas now, so on any screen narrower than that the track
   became 1500px, started at the left edge, overflowed to the right, and `place-items:center` had
   nothing left to do. Scaling then shrank the slide about the centre of THAT box, which sits to the
   right of the stage's own centre — the content pushed right.
   `left:50%` with `translate(-50%,-50%)` cannot be fooled by track sizing: the slide is centred on
   the stage whatever size it is, and the clip takes whatever hangs over. */
/* THE SCALE LIVES ON THE STAGE (2026-09-01, user: "a weird formatting jumping break ... moving
   from one slide to another"). It was declared on the SLIDE, so each slide carried its own `--fit`
   and the type changed size on every move. Declared here it is inherited by every slide in the
   deck, and one value governs the whole presentation. A custom property declared on the element
   would beat the inherited one, so it has to come OFF the slide as well as go on here. */
.pdeck-stage{--fit:1;position:relative;z-index:1;flex:1;min-height:0;overflow:hidden}
.pdeck-stage>.pdeck-slide{position:absolute;left:50%;top:50%;min-width:0}
.pdeck-prog{position:relative;z-index:2;height:2px;background:var(--line-08)}
.pdeck-prog-on{height:100%;width:0;background:var(--hl);transition:width .5s var(--ease);
  box-shadow:0 0 12px rgba(255,255,255,.55)}
/* THE CHROME STANDS DOWN when nothing has moved for a few seconds, and comes back on any movement. */
.pdeck-bar{transition:opacity .5s var(--ease)}
.pdeck.idle .pdeck-bar{opacity:0}
.pdeck.idle{cursor:none}

/* THE SLIDE ITSELF, at room size. Everything steps up: this is read from across a table, or from
   the back of a boardroom, not from a document in the hand. */
/* THE HANDOVER. A slide arrives from the direction of travel and the one it replaces leaves the
   other way, so a deck reads as movement rather than as a stack of replacements. */
/* THE SLIDE IS A FIXED CANVAS AND THE SCALE IS WHAT ADAPTS (2026-08-31, user). It used to be
   `width:100%` up to 1500px, so a narrow or short screen RE-LAID-OUT the slide: type clamped down
   on width, grids reflowed, and the composition stopped being the one that was designed. A fixed
   width means the layout is identical on every screen and only `--fit` differs, which is what
   "preserving format" means. `--fit` is set ONCE FOR THE DECK on `.pdeck-stage`, off its tallest
   slide, and it is never above 1:
   a big screen still gets the slide at its designed size rather than a blown-up one.
   THE SCALE RIDES ON EVERY HANDOVER STATE, or the slide would spring to full size as it arrives.
   The translate is listed first so the slide-in distance stays the same at any scale. */
/* THE CANVAS IS FIXED IN BOTH DIRECTIONS (2026-09-01, user: "the presentation is still jumping").
   THIS IS THE JUMP THAT SURVIVED EVERYTHING ELSE. The width was fixed and the HEIGHT never was, so
   every slide was as tall as its own content and was then centred on the stage: the cover is short,
   a forecast table is tall, and the heading, the body and the footer therefore sat at a DIFFERENT
   HEIGHT ON EVERY SLIDE. Moving through the deck slid the whole composition up and down, which is
   a formatting jump in the most literal sense and is not something a scale can fix.
   844 IS A FLOOR, NOT A CEILING. A first attempt fixed the height outright and made things worse:
   the fit measures the slide's box, so a box pinned at 844 told it every slide already fitted, and
   a ten-year table simply overflowed and was CLIPPED at year seven with nothing said. Every slide
   is at least 844 (1500 x 844 is 16:9, the shape of the room's screen) and the deck then takes the
   height of its TALLEST slide, `--deck-h`, and gives it to all of them. Same position on every
   slide, nothing cut off, and one scale over the lot.
   THE HEADING IS PINNED AT THE TOP AND THE FOOTER AT THE BOTTOM, with the slack in between, which
   is exactly what the paper skin already does with a growing body box. The stage cannot use that
   box — its arrival staggers `.pdeck-slide.stage.in > *`, so a wrapper would collapse the whole
   slide into one delay — so the footer takes the slack with `margin-top:auto`, which it has always
   declared and which did nothing at all while there was no slack for it to take. */
.pdeck-slide.stage{--pdeck-mark-w:240px;
  width:1500px;min-height:844px;height:var(--deck-h,auto);display:flex;flex-direction:column;gap:var(--sp-4);
  padding:var(--sp-4) 0;position:relative;opacity:0;transform-origin:center center;
  transform:translate(-50%,-50%) scale(var(--fit));
  transition:opacity .45s var(--ease),transform .55s var(--ease)}
.pdeck-slide.stage.from-right{transform:translate(-50%,-50%) translateX(56px) scale(var(--fit))}
.pdeck-slide.stage.from-left{transform:translate(-50%,-50%) translateX(-56px) scale(var(--fit))}
.pdeck-slide.stage.in{opacity:1;transform:translate(-50%,-50%) scale(var(--fit))}
.pdeck-slide.stage.out-left{opacity:0;transform:translate(-50%,-50%) translateX(-46px) scale(var(--fit))}
.pdeck-slide.stage.out-right{opacity:0;transform:translate(-50%,-50%) translateX(46px) scale(var(--fit))}
/* THE CONTENT SITS IN THE MIDDLE, BETWEEN THE HEADING AND THE FOOTER (2026-09-01, user: "the
   content is now not centered"). Every slide is given the height of the tallest, which is what
   holds the composition still, and a short slide then had all of its slack below it. The footer
   already takes the slack with `margin-top:auto`; giving the FIRST thing under the heading an auto
   margin as well makes the two share it, which centres everything between them. */
/* THE HEADING IS PART OF WHAT IS CENTRED (2026-09-01, user: "the headings are now at the top of
   the page and not centred with the rest of the content"). The auto margin was on the first thing
   UNDER the heading, so the heading stayed pinned at the top and only the body moved down. Put it
   on the heading itself and the whole block — heading and content together — sits in the middle,
   with the footer still taking the slack below it. */
.pdeck-slide.stage > .pdeck-head{margin-top:auto}

/* ONE CARD PER STRUCTURE, WITH THE FIGURE CARRYING IT (2026-09-01, user). The label is small above
   the number, and the FIRST figure on each card is the one the argument exists to produce. */
/* THE CARDS LINE UP EVEN WHEN ONE TITLE WRAPS (2026-09-01, from his screenshot: "Option 2 ·
   Revenue share" took two lines and pushed its figures below the other two). The heading keeps two
   lines' worth of room whether it needs them or not, which is deterministic on a fixed canvas. */
.pdoc-optcard{display:flex;flex-direction:column;gap:2px}
.pdoc-optcard h4{min-height:2.5em}
.pdoc-optcard h4{margin-bottom:var(--sp-2)}
.pdoc-optcard .cap{margin-top:var(--sp-2)}
.pdeck-slide.stage .pdoc-optcard .pdoc-tile-v.lead{color:#fff}
/* THE COVER'S FIGURE SITS UNDER THE DISPLAY LINE, NOT OVER IT (2026-09-01). `.pdeck-big` is the
   112px used on a slide whose whole job is one number; on the cover it would outshout the display
   line above it. Pixels rather than a token because this canvas is fixed and sized in pixels
   throughout: a viewport unit here is what made the deck re-lay-out. */
/* AND ON THE COVER IT SITS UNDER THE TITLE IN SIZE AS WELL AS POSITION (2026-09-23, user: "the
   font is too large on the your assets evolved and earning for the money figure of the option
   shown"): the 64px still outshouted the 56px display line above it, so the figure steps below
   it on both skins. */
.pdeck-slide.stage.cover .pdeck-big{font-size:44px;margin-top:4px}
/* THE COVER, PASS FIVE (2026-09-10, user: "put the screenshot in a card and put it on the
   right of the logo card and centre all the content (also remove top 2 dividers)"): the header
   block on max two lines with the tagline under it, then ONE row of two cards, the lockup left
   and the figures right, everything centred on the page. The rules are gone. */
/* PASS SIX (2026-09-10, user): the title left on one or two lines, the two cards the SAME
   SIZE (each half the row), and the landlord + address line closing the block. */
.pdeck-slide.stage.cover{align-items:flex-start;justify-content:flex-start;gap:var(--sp-4)}
/* the cover's display steps down to sit with the rest of the deck (2026-09-11, user: "match
   the font size so it is more in line with the rest of the presentation"), the title slide's
   own 56px so the two openings read as one system */
.pdeck-slide.stage.cover > .pdeck-display{margin-top:auto;max-width:1080px;text-align:left;
  font-size:56px;line-height:1.08}
.pdeck-slide.stage.cover .pdeck-tag{text-align:left}
.pdeck-cv-row{display:flex;align-items:stretch;gap:var(--sp-5);align-self:stretch;
  flex:0 0 auto;max-width:100%}
.pdeck-cv-row>*{flex:1 1 0;min-width:0}
.pdeck-cv-lockup{display:flex}
.pdeck-cv-lockup .pdeck-collab{flex:1 1 auto;align-self:stretch;align-items:stretch;
  max-width:none;margin-top:0}
.pdeck-cv-lockup .pdeck-collab-card{flex:1 1 auto;width:100%;justify-content:center;
  align-items:center}
.pdeck-cv-figs{display:flex;flex-direction:column;justify-content:center;gap:10px;
  border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch) 0 var(--notch) 0;min-width:0}
/* the tagline that closes the cover came up a step (2026-09-11, user: "increase the size of
   the tagline"), on both skins */
.pdeck-cv-meta{align-self:flex-start}
.pdeck-slide.stage.cover .pdeck-cv-meta{font-size:20px}
.pp-sheet.paper .pdeck-slide.cover .pdeck-cv-meta{font-size:11.5pt}
.pdeck-slide.stage.cover .pdeck-cv-row{margin-top:var(--sp-4)}
/* the figures card is the FRAME alone (2026-09-11, user: "remove the background of the card
   that has the financial figures"): the hairline stays, the lit fill goes, on every skin */
.pdeck-slide.stage.cover .pdeck-cv-figs{padding:56px 64px}
/* the lockup card's internal air, his 18 percent, fixed on the fixed canvas */
.pdeck-slide.stage.cover .pdeck-collab-card{padding:64px 72px}
/* 1:1 balance on the cover lockup, his word: both marks the same height there. The two size
   sliders ride the heights as vars (2026-09-11), so 1:1 is the sliders' starting point. */
.pdeck-slide.stage.cover .pdeck-collab .pdeck-evolv{height:calc(100px*var(--evsc,1));
  max-height:calc(100px*var(--evsc,1))}
.pdeck-slide.stage.cover .pdeck-collab{margin-top:0}

/* AND THE CONTENT IS VISIBLE WHETHER OR NOT ITS ARRIVAL EVER RAN (2026-09-01, user: the first slide
   showing "just the logos").
   THE ARRIVAL ANIMATIONS FILL `both`, which means an element whose animation has not started yet
   holds the FROM state, and that state is opacity 0. Anything that stops those animations running
   — and the fullscreen transition landing on the first slide is one such thing — therefore leaves
   the slide up with most of it invisible, permanently, until the node is rebuilt.
   A PRESENTATION MUST FAIL TOWARDS SHOWING THE CONTENT. `settled` is put on a moment after the
   slide arrives and pins everything visible: the animation plays when it can, and when it cannot
   the room still sees the slide. It is a net, not the mechanism, and it is declared after the
   arrival rules so it wins on order rather than on `!important`. */
.pdeck-slide.stage.settled > *,
.pdeck-slide.stage.settled .pdeck-item > *:not(.card-trace),
.pdeck-slide.stage.settled .pdoc-tile > *:not(.card-trace),
.pdeck-slide.stage.settled .card > *:not(.card-trace),
.pdeck-slide.stage.settled .pdoc-formula,
.pdeck-slide.stage.settled .pdoc-fig img{animation:none;opacity:1;transform:none}
/* THE RULE DRAWS ITSELF, which is the brand's own move for a divider, and a single LED glint
   sweeps the title once as the slide settles. Neither repeats: this is punctuation, not decoration. */
.pdeck-slide.stage .pdeck-title{display:flex;align-items:center;gap:14px;position:relative;
  font-family:var(--font-display);text-transform:uppercase;font-size:39px;
  letter-spacing:var(--ls-btn);color:#fff;overflow:hidden}
/* the drawn rule lives on the HEAD ROW now (2026-09-10, user: "make sure the divider lines are
   the same length"): under the title AND the landlord's card, the footer's full measure */
.pdeck-slide.stage .pdeck-head{position:relative;padding-bottom:var(--sp-3)}
.pdeck-slide.stage .pdeck-head::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--line-14);transform:scaleX(0);transform-origin:left center}
.pdeck-slide.stage.in .pdeck-head::after{animation:deckDraw .7s var(--ease) .12s both}
.pdeck-slide.stage .pdeck-title::before{content:"";position:absolute;top:0;bottom:0;width:38%;
  left:-40%;pointer-events:none;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.10) 45%,transparent);
  opacity:0}
.pdeck-slide.stage.in .pdeck-title::before{animation:deckGlint 1.1s var(--ease) .28s both}
@keyframes deckDraw{ from{transform:scaleX(0)} to{transform:scaleX(1)} }
@keyframes deckGlint{ 0%{left:-40%;opacity:0} 18%{opacity:1} 100%{left:110%;opacity:0} }
.pdeck-slide.stage .pdeck-title .sec-icon{width:1em;height:1em;color:var(--hl);opacity:1}
.pdeck-slide.stage .pdeck-display{font-family:var(--font-display);text-transform:uppercase;
  font-size:83px;line-height:1;color:#fff;letter-spacing:var(--ls-display)}
.pdeck-slide.stage .pdeck-big{font-family:var(--font-display);
  font-size:112px;line-height:1;color:#fff}
/* THE TAGLINE CARRIES THE COVER (2026-08-27, user). It was set at caption size under a display
   line four times its height, which read as a footnote to the thing it is supposed to introduce. */
/* THE TAGLINE CARRIES THE COVER AND IT SITS ON ONE LINE (2026-08-27, user). The measure comes off
   so it cannot wrap.
   IT IS SIZED IN PIXELS, NOT vw (2026-09-01, user: "fix the damn presentation jumping"). THIS WAS
   THE JUMP, and everything else was a symptom of it. The slide is a FIXED 1500px canvas scaled by
   `--fit`, and the type and the pictures inside it were sized against the VIEWPORT: every heading,
   the display line, this tagline, the tile figures and the site images all re-sized whenever the
   window did — which includes the moment full screen changes it, right after the deck has been
   measured. So the deck was measured at one set of sizes and then drawn at another: slides
   overflowed, tables were cut off, and the composition moved every time.
   A FIXED CANVAS MAY NOT CONTAIN A VIEWPORT UNIT. The values here are what the clamps resolved to
   at the 1500px design width, so it looks as it was tuned to and can no longer change shape. */
.pdeck-slide.stage .pdeck-tag{font-size:31px;line-height:1.2;
  color:var(--grey-70);margin-top:var(--sp-3);white-space:nowrap}
.pp-sheet.paper .pdeck-tag{font-size:15pt;color:#10172B;margin-top:var(--sp-3);white-space:nowrap}
.pdeck-slide.stage .cap{font-size:var(--fs-4);letter-spacing:.06em}
.pdeck-slide.stage p{font-size:var(--fs-5);line-height:1.55;color:var(--grey-70);max-width:70ch}
.pdeck-slide.stage .pdeck-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--sp-4)}
/* the spec page breathes on the stage too (2026-09-10): two columns held off the canvas edge,
   and the rows inset INSIDE their columns */
.pdeck-slide.stage.spec .pdeck-grid{grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--sp-6);width:92%;align-self:center}
.pdeck-slide.stage.spec .pdeck-item{padding:var(--sp-3) 26px}
.pdeck-slide.stage .pdeck-item{padding:var(--sp-4);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch) 0 var(--notch) 0;background:rgba(255,255,255,.02)}
.pdeck-slide.stage .pdeck-item h4{font-family:var(--font-display);text-transform:uppercase;
  font-size:var(--fs-5);letter-spacing:var(--ls-btn);color:#fff;margin-bottom:8px}
/* the icon leads the card, at room size, in the same framed tile the tab uses */
.pdeck-slide.stage .pdeck-item .why-ico{width:52px;height:52px;margin-bottom:var(--sp-2);
  border-color:var(--line-14);background:rgba(255,255,255,.03)}
.pdeck-slide.stage .pdeck-item .why-ico .sec-icon{width:26px;height:26px;color:var(--hl);opacity:1}
.pdeck-slide.stage .pdeck-pics{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-3)}
/* THE SITE FILLS THE STAGE. The mockup leads at nearly two thirds, the map beside it, both whole
   rather than cropped: this is the picture the landlord came to look at. */
/* TWO THIRDS TO THE SITE, ONE THIRD TO THE MAP (2026-08-28, user). The same split on the printed
   page, so the room and the paper frame the property the same way. */
.pdeck-slide.stage .pdeck-pics.site{grid-template-columns:2fr 1fr;gap:var(--sp-4);align-items:start}
.pdeck-slide.stage .pdeck-pics.site .pdoc-fig img{width:100%;height:auto;aspect-ratio:auto;
  max-height:470px;object-fit:contain}
.pdeck-slide.stage .pdeck-pics.site .pdoc-fig:only-child img{max-height:520px}
.pdeck-slide.stage .pdeck-pics .pdoc-fig img{width:100%;aspect-ratio:16/10;object-fit:cover;height:auto;
  border-radius:var(--notch) 0 var(--notch) 0;border:var(--stroke) solid var(--line-14)}
/* pictures settle rather than appear */
.pdeck-slide.stage.in .pdoc-fig img{animation:deckSettle 1.15s cubic-bezier(.22,.61,.30,1) .2s both}
@keyframes deckSettle{ from{opacity:.25;transform:scale(1.07)} to{opacity:1;transform:none} }
.pdeck-slide.stage .pdoc-tbl{font-size:var(--fs-5)}
.pdeck-slide.stage .pdoc-tbl th{font-size:var(--fs-2)}
.pdeck-slide.stage .pdoc-tbl th,.pdeck-slide.stage .pdoc-tbl td{padding:12px 14px}
.pdeck-slide.stage .pdoc-tiles{gap:var(--sp-3)}
.pdeck-slide.stage .pdoc-tile{padding:var(--sp-4)}
.pdeck-slide.stage .pdoc-tile-v{font-size:38px}
.pdeck-slide.stage .pdoc-optcard .pdoc-tile-v{font-size:30px}
.pdeck-slide.stage .pdoc-optcard .pdoc-tile-v.lead{font-size:44px}
.pdeck-slide.stage .pdoc-tile.big .pdoc-tile-v{font-size:54px}
.pdeck-slide.stage .pdoc-row{padding:12px 0}
.pdeck-slide.stage .pdoc-row-v{font-size:var(--fs-5)}
.pdeck-slide.stage .pdoc-formula{font-size:var(--fs-4);padding:var(--sp-3) var(--sp-4)}
.pdeck-slide.stage .pdeck-foot{margin-top:auto;padding-top:var(--sp-3);color:var(--grey-22)}
/* the corner mark's own rule lives with the rest of the mark's, under THE LANDLORD'S MARK below.
   It was declared twice, here and there, from 2026-08-28 until the duplicate was found. */

/* ---- THE CARDS DRAW THEMSELVES IN (2026-08-27, user, revised twice) ----
   THE FRAME FOLLOWS THE CI SHAPE. It is a measured path, drawn with a dash offset, so it runs the
   whole way round the cut-frame: sharp at top-right and bottom-left, rounded at top-left and
   bottom-right. Four straight lines could not do that, which is why the corners looked cut off.
   Then the words fade up, then the glint passes. One pass, nothing loops.
   A card keeps its ordinary hairline until a path is attached, so anything without layout just
   shows the frame. */
.pdeck-slide.stage .pdeck-item,
.pdeck-slide.stage .pdoc-tile,
.pdeck-slide.stage .pdoc-formula,
.pdeck-slide.stage .card{position:relative;overflow:visible;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pdeck-slide.stage .traced{border-color:transparent}
.card-trace{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible}
.card-trace path{fill:none;stroke:var(--hl);stroke-width:1;opacity:.55;
  vector-effect:non-scaling-stroke}
.card-trace path.draw{animation:cardDraw 1.6s cubic-bezier(.22,.61,.30,1) both}
@keyframes cardDraw{
  from{stroke-dashoffset:var(--len);opacity:.85}
  to  {stroke-dashoffset:0;opacity:.55}
}

/* the glint passes over the finished frame, once */
.pdeck-slide.stage .pdeck-item::before,
.pdeck-slide.stage .pdoc-tile::before,
.pdeck-slide.stage .pdoc-formula::before,
.pdeck-slide.stage .card::before{content:"";position:absolute;top:0;bottom:0;width:45%;
  left:-46%;pointer-events:none;border-radius:inherit;opacity:0;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.09) 46%,transparent)}
.pdeck-slide.stage.in .pdeck-item::before,
.pdeck-slide.stage.in .pdoc-tile::before,
.pdeck-slide.stage.in .pdoc-formula::before,
.pdeck-slide.stage.in .card::before{animation:cardGlint 1.2s var(--ease) 1.1s both}

/* THE WORDS ARRIVE WHILE THE FRAME IS STILL DRAWING (2026-09-01, user: text "mssing from the
   visual deck"). They used to wait 1.15s for the cut-frame to close and then take a further .95s,
   so a slide was unreadable for over two seconds and anybody presenting at a normal pace moved on
   before the figures existed. `both` holds the FROM state through the delay, which is opacity 0,
   so what he saw was not slow: it was blank.
   THE ORDER IS KEPT AND ONLY THE WAIT IS CUT: frame, then words, then the glint over the top. */
.pdeck-slide.stage.in .pdeck-item>*:not(.card-trace),
.pdeck-slide.stage.in .pdoc-tile>*:not(.card-trace),
.pdeck-slide.stage.in .card>*:not(.card-trace){animation:cardWords .5s cubic-bezier(.22,.61,.36,1) .3s both}
.pdeck-slide.stage.in .pdoc-formula{animation:cardWords .5s cubic-bezier(.22,.61,.36,1) .3s both}
/* inside a card the lines follow each other rather than arriving as a block */
.pdeck-slide.stage.in .pdeck-item>*:nth-child(3){animation-delay:.38s}
.pdeck-slide.stage.in .pdeck-item>*:nth-child(4){animation-delay:.46s}
.pdeck-slide.stage.in .pdoc-tile>*:nth-child(3){animation-delay:.38s}
.pdeck-slide.stage.in .pdoc-tile>*:nth-child(4){animation-delay:.46s}

@keyframes cardWords{ from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:none} }
@keyframes cardGlint{ 0%{left:-46%;opacity:0} 22%{opacity:1} 100%{left:112%;opacity:0} }

/* THE CONTENT ARRIVES IN ORDER, so the eye is led rather than hit. Nothing bounces. */
.pdeck-slide.stage.in > *{animation:deckRise .55s var(--ease) both}
.pdeck-slide.stage.in > *:nth-child(2){animation-delay:.05s}
.pdeck-slide.stage.in > *:nth-child(3){animation-delay:.11s}
.pdeck-slide.stage.in > *:nth-child(4){animation-delay:.17s}
.pdeck-slide.stage.in > *:nth-child(5){animation-delay:.23s}
.pdeck-slide.stage.in > *:nth-child(n+6){animation-delay:.29s}
@keyframes deckRise{ from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:none} }
@media (prefers-reduced-motion:reduce){
  .pdeck-slide.stage,.pdeck-slide.stage.in > *,.pdeck-glow,
  .pdeck-slide.stage.in .pdeck-title::after,.pdeck-slide.stage.in .pdeck-title::before,
  .pdeck-slide.stage.in .pdeck-item::after,.pdeck-slide.stage.in .pdoc-tile::after,
  .pdeck-slide.stage.in .pdeck-item>*,.pdeck-slide.stage.in .pdoc-tile>*,
  .pdeck-slide.stage.in .pdoc-fig img{animation:none;transition:none;opacity:1;transform:none;
    clip-path:none}
  .pdeck-slide.stage .pdeck-item::before,.pdeck-slide.stage .pdoc-tile::before{display:none}
  .pdeck-slide.stage .pdeck-item,.pdeck-slide.stage .pdoc-tile,
  .pdeck-slide.stage .pdoc-formula,.pdeck-slide.stage .card{border-color:var(--line-14)}
  .card-trace{display:none}
  .pdeck-slide.stage.in .pdoc-formula,.pdeck-slide.stage.in .card>*,
  .pdeck-slide.stage.in .pdeck-item>*,.pdeck-slide.stage.in .pdoc-tile>*{animation:none;opacity:1;
    transform:none}
  .pdeck-slide.stage .pdeck-title::after{transform:scaleX(1)}
  .pdeck-slide.stage .pdeck-title::before{display:none}
  .pdeck.idle .pdeck-bar{opacity:1}
}

/* the top bar's own toggle, available on every screen */
.fs-btn .sec-icon{width:1.05em;height:1.05em;color:currentColor;opacity:.9}
body.is-fullscreen .fs-btn{color:var(--hl)}

/* ---- THE BUILDER, AND THE PRINT THAT MATCHES IT (2026-08-27, user) ----
   Pagination is ours, not the browser's: a page is a fixed A4 box on screen AND on paper, so what
   the builder shows is what comes out. 794 x 1123 CSS pixels is A4 at 96dpi. */
.pp-wrap{display:flex;flex-direction:column;gap:var(--sp-3)}
/* ONE HEIGHT ACROSS THE BAR (2026-09-11, user: the controls read as disjointed). Five different
   control heights sat on one row; --ppb-h is the one number they all share now. The deckmode
   group also resets the .tabs base margin, whose var(--sp-4) bottom was pushing Light/Dark off
   the bar's centreline. */
.pp-bar{--ppb-h:46px;display:flex;align-items:center;gap:12px;flex-wrap:wrap;row-gap:10px}
.pp-bar .btn{height:var(--ppb-h);padding-top:0;padding-bottom:0}
.pp-deckmode{display:flex;gap:6px;flex:0 0 auto;margin:0}
.pp-deckmode .tab{height:var(--ppb-h);padding:0 18px;display:inline-flex;align-items:center}
.pp-modes{display:flex;gap:8px;flex-wrap:wrap}
.pp-mode{display:flex;flex-direction:column;justify-content:center;gap:2px;align-items:flex-start;
  height:var(--ppb-h);padding:0 16px;
  cursor:pointer;background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:var(--grey-70);font:inherit;
  transition:border-color var(--t-micro) var(--ease),color var(--t-micro) var(--ease)}
.pp-mode:hover{color:#fff;border-color:var(--line-40)}
.pp-mode.on{color:#fff;border-color:var(--hl)}
.pp-mode-l{font-family:var(--font-display);text-transform:uppercase;font-size:var(--fs-2);
  letter-spacing:var(--ls-btn)}
.pp-body{display:flex;gap:var(--sp-4);align-items:flex-start}
.pp-side{flex:0 0 290px;display:flex;flex-direction:column;gap:10px}
.pp-rail{display:flex;flex-direction:column;max-height:70vh;overflow:auto}
.pp-row{display:flex;align-items:center;gap:8px;padding:7px 8px;
  border-top:var(--stroke) solid var(--line-08)}
.pp-row:first-child{border-top:0}
.pp-row.on{background:rgba(255,255,255,.04)}
.pp-row.out .pp-t,.pp-row.out .pp-n{color:var(--grey-22);text-decoration:line-through}
.pp-row input{width:15px;height:15px;accent-color:var(--hl);flex:0 0 auto}
.pp-row-l{flex:1 1 auto;min-width:0;display:flex;align-items:baseline;gap:9px;background:none;
  border:0;padding:0;cursor:pointer;text-align:left;font:inherit;color:inherit}
.pp-n{font-family:var(--font-display);font-size:var(--fs-1);color:var(--grey-45);flex:0 0 auto}
.pp-t{color:var(--grey-70);font-size:var(--fs-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pp-row.on .pp-t{color:#fff}
.pp-mv{flex:0 0 auto;opacity:.55}
.pp-mv:hover{opacity:1}
.pp-goto,.pp-note{margin-top:6px}
/* THE WHOLE PAGE AT ONCE (2026-08-27, user). The view has a definite height so a page can be
   scaled to fit inside it; the scaler carries the scaled size so the scroll area stays honest. */
.pp-view{flex:1 1 auto;min-width:0;overflow:auto;padding:14px;height:calc(100vh - 230px);
  min-height:420px;display:flex;flex-direction:column;align-items:center}
.pp-scale{transform-origin:top center;flex:0 0 auto}
/* the zoom rides the bar's own geometry rather than floating bare between framed buttons */
.pp-zoom{display:flex;align-items:center;gap:9px;height:var(--ppb-h);padding:0 14px;
  background:rgba(255,255,255,.015);border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pp-zoom input[type=range]{width:120px;accent-color:var(--hl)}
.pp-zoom-v{min-width:44px;text-align:right}
/* A PAGE IS A4 OR IT IS NOT A PAGE (2026-08-28, user: "some i can see are not a4 in the visual
   deck"). This was `min-height`, so a sheet with too much on it simply grew — and because the
   builder's warning asks whether `scrollHeight` exceeds `clientHeight`, a sheet that grows to fit
   its own content can never trip it. The box is FIXED at A4 now, in both orientations, so what
   overflows is clipped exactly as the printer would clip it and the warning says so. */
.pp-sheet{display:flex;flex-direction:column;width:794px;height:1123px;padding:48px;background:var(--black);
  border:var(--stroke) solid var(--line-14);box-shadow:0 18px 60px rgba(0,0,0,.55);
  margin:0 auto;overflow:hidden}
.pp-sheet.landscape{width:1123px;height:794px}
.pp-sheet.out{opacity:.35}
.pp-sheet .pdoc-sec,.pp-sheet .pdeck-slide{gap:var(--sp-3)}
.pp-sheet .pdeck-slide{min-height:auto;padding:0}
.pp-print{display:none}

/* ---- THE PORTRAIT DOCUMENT: A PRINTED DOCUMENT, ON PAPER (2026-08-27, user) ----
   IT PRINTS ON WHITE, and the ink is EVOLV Navy #10172B rather than grey. Grey on white reads as
   washed out on paper in a way it does not on a screen, which is why the lead paragraph looked
   half-erased. Everything below is one ink at different strengths: full for headings and figures,
   about three quarters for prose, about half for labels, and a hairline for rules.
   Even padding, and MORE AT THE TOP so a page has air above its heading. */
.pp-sheet{padding:72px 56px 56px}
/* THE HEADER ROW MUST NOT PUSH A SLIDE OFF THE SHEET (2026-09-10, user: "ensure that everything
   fits on the page even if you have to scale down a bit"). The landscape deck pays for its new
   header out of the sheet's own top air and the title's margin, not out of the content. */
.pp-sheet.landscape{padding-top:44px}
.pp-sheet.paper{--pdeck-mark-w:165px;background:#FFFFFF;color:#10172B;border-color:#D8DCE4}
/* the card edges came up a second step (2026-09-10, user: "the general contrast on the white is not right make the cards a bit heavier") */
.pp-sheet.paper .card{background:#FFFFFF;border-color:rgba(16,23,43,.22);box-shadow:none}
.pp-sheet.paper .card::before,.pp-sheet.paper .card::after,.pp-sheet.paper .shine{display:none}
.pp-sheet.paper h2,.pp-sheet.paper h3,.pp-sheet.paper strong{color:#10172B}
.pp-sheet.paper .pdoc-display,.pp-sheet.paper .pdoc-sum-v,.pp-sheet.paper .pdoc-tile-v,
.pp-sheet.paper .pdoc-row-v,.pp-sheet.paper .pdoc-tbl td:first-child{color:#10172B}
.pp-sheet.paper .pdoc-sub{color:#10172B}
/* THE INK CAME UP (2026-09-09, user: "double check the contrast values as they look a little
   weak"). Every muted paper value strengthened; the hierarchy is kept by the spread, not by
   fading the small text out. */
.pp-sheet.paper .pdoc-p{color:rgba(16,23,43,.88)}
.pp-sheet.paper .cap{text-transform:none;letter-spacing:0;font-size:9.5pt;
  color:rgba(16,23,43,.7);font-weight:400}
.pp-sheet.paper .pdoc-row{border-color:rgba(16,23,43,.10)}
.pp-sheet.paper .pdoc-tbl th{color:rgba(16,23,43,.7);border-color:rgba(16,23,43,.24);
  text-transform:uppercase;letter-spacing:.08em;font-size:8.5pt}
.pp-sheet.paper .pdoc-tbl td{color:rgba(16,23,43,.86);border-color:rgba(16,23,43,.12)}
/* AND THE FORMULA IS INKED (2026-09-01, from the same screenshot: it was all but invisible). The
   base rule sets `color:#fff` for the dark deck and the paper skin restyled the BOX and never the
   text, so it printed white on near-white. */
.pp-sheet.paper .pdoc-tile,.pp-sheet.paper .pdoc-sum-tile,.pp-sheet.paper .pdoc-formula{
  background:#F4F6FA;border-color:rgba(16,23,43,.18)}
.pp-sheet.paper .pdoc-formula,.pdeck.paper .pdoc-formula{color:#10172B}
.pp-sheet.paper .why-ico{background:#F4F6FA;border-color:rgba(16,23,43,.16)}
.pp-sheet.paper .sec-icon{color:#10172B;opacity:.9}
.pp-sheet.paper .pdoc-foot{border-color:rgba(16,23,43,.14)}
.pp-sheet.paper .pdoc-foot .cap{color:rgba(16,23,43,.62)}
.pp-sheet.paper .pdoc-principle-n{color:rgba(16,23,43,.5)}
.pp-sheet.paper .chip{background:#F4F6FA;color:#10172B;border-color:rgba(16,23,43,.12)}

/* the page's own rhythm. Print measurements: 682px of content inside a 794px A4. */
/* THE PAGE IS A FIXED BOX AND ITS CONTENT CLIPS INSIDE IT (2026-09-09, user: "ensure the
   location of the footer and such items does not change"). `min-height` let a heavy page GROW
   past the sheet: the principle cards ran into the footer band and the sheet's own edge cut
   their bottoms off in the print. The height is exact now, every page-level child clips its own
   overflow, and the footer keeps one position on every sheet. The builder's overflow warning
   asks the CHILDREN now, not the sheet, or this fix would have killed it (the 2026-08-28
   min-height trap, one layer in). */
.pp-sheet .pdoc{display:flex;flex-direction:column;gap:var(--sp-4);height:995px;min-height:0}
.pp-sheet.landscape .pdoc{height:666px}
.pp-sheet .pdoc>.pdoc-sec,.pp-sheet .pdoc>.pdoc-cover,.pp-sheet .pdoc>.pdoc-title,
.pp-sheet .pdoc>.pdoc-thanks{flex:1 1 auto;min-height:0;overflow:hidden}
.pp-sheet .pdoc>.pdoc-foot{flex:0 0 auto}
/* THE RULE NEEDS AIR UNDER IT (2026-08-27, user). The heading, its rule, then a clear gap before
   the content: without it the divider reads as an underline on the heading rather than as the
   break between the two. */
.pp-sheet .pdoc-sec{display:flex;flex-direction:column;gap:var(--sp-3)}
/* EQUAL EITHER SIDE OF THE RULE (2026-08-27, user). The section's own gap already puts --sp-3
   under the rule and the margin adds another, so the space above it is set to match that total
   rather than to a number that only looks right on one page. */
.pp-sheet .pdoc-head{margin-bottom:var(--sp-3)}
/* THE RULE UNDER A HEADING IS THE BREAK (2026-08-27, user), and there is never a second one at the
   foot of a section: the page itself ends it. */
.pp-sheet .pdoc-head{padding-bottom:var(--sp-5);border-bottom:1px solid rgba(16,23,43,.14)}
.pp-sheet:not(.paper) .pdoc-head{border-bottom-color:var(--line-14)}
.pp-sheet .pdoc-head h2{font-size:22pt;line-height:1.12}
.pp-sheet .pdoc-card{padding:var(--sp-3)}
.pp-sheet .pdoc-card h3{font-size:11.5pt}
/* THE THREE OPTIONS ARE THREE COLUMNS ON THE PAGE (2026-08-31, user: "make sure that the option
   comparison can fit on one page"). `auto-fit` with a 240px minimum works out to TWO columns in an
   A4 type area, so the third option wrapped onto a row of its own and ran off the bottom of the
   sheet. The class is called `pdoc-grid-3`; on paper it now is one. Everything below is what makes
   a comparison card readable at a third of the measure rather than a half. */
/* THE OPTION CARDS FILL THE ROW WHATEVER IS OFFERED (2026-09-09, user): one, two or three share
   the whole measure, so a two-option page never shows a dead third column. Flex, not auto-fit:
   auto-fit resolving to two across is the 2026-08-31 overflow this rule replaced. */
.pp-sheet .pdoc-grid-3{display:flex;grid-template-columns:none;gap:var(--sp-3)}
.pp-sheet .pdoc-grid-3>*{flex:1 1 0;min-width:0}
/* four structures on one A4 read as two by two (2026-10-08, Option 4); four across is too narrow */
.pp-sheet .pdoc-grid-3.n4{flex-wrap:wrap}
.pp-sheet .pdoc-grid-3.n4>*{flex:1 1 calc(50% - var(--sp-3))}
/* AND THE MINI VALUATION AND YIELD CARDS FLEX THE SAME WAY (2026-09-09, user: "apply the flex
   idea to the mini option summary comparison"). Scoped to the DOCUMENT's sections only: the
   printed deck slides keep their own three-column grid.
   RE-WON 2026-09-11 (user, from his renders: two cards and a third column of dead space): the
   2026-09-10 deck rule `.pp-sheet.paper .pdeck-grid` ties this selector at (0,3,0) and is
   declared LATER, so it was quietly winning and the flex was dead on the very pages it was
   written for. The document's selector carries `.paper` now, (0,4,0), and outranks it. */
.pp-sheet.paper .pdoc-sec .pdeck-grid{display:flex;grid-template-columns:none;gap:var(--sp-3);
  align-items:stretch}
.pp-sheet.paper .pdoc-sec .pdeck-grid>*{flex:1 1 0;min-width:0}
/* four structures stay four in a row on the A4 (2026-10-08): with the short heading and the
   composition on its own line they fit, and two by two made the principles pages clip; a heading
   may never spill out of its card */
.pdoc-optcard h4{overflow-wrap:anywhere}
.pdoc-optcard .cap.pdoc-optcard-note{margin-top:0;margin-bottom:var(--sp-2)}
/* three or more structures on the DOCUMENT's page are a compact table (2026-10-08); the deck draws the
   same rows as cards, so each surface shows its own and hides the other */
.pdoc-optable{width:100%;border-collapse:collapse;margin-top:var(--sp-2)}
.pdoc-optable th{font-size:var(--fs-1);text-transform:uppercase;letter-spacing:.06em;font-weight:400;text-align:left;
  padding:3px 8px;opacity:.7;border-bottom:var(--stroke) solid currentColor}
.pdoc-optable td{padding:3px 8px;vertical-align:top;border-bottom:var(--stroke) solid rgba(127,127,127,.25)}
.pdoc-optable td .cap{line-height:1.25;margin:0}
.pdoc-optable-n{font-family:var(--font-display);text-transform:uppercase;font-size:var(--fs-2);letter-spacing:.02em}
.pdoc-optable-v{text-align:right;white-space:nowrap;font-size:var(--fs-3)}
.pdoc-optable-v.lead{font-weight:700}
.pdoc-optable th:not(:first-child){text-align:right}
.pdoc .pdoc-optable-deck{display:none}
.pdeck-slide .pdoc-optable{display:none}

/* the landscape deck has the width for four in a row, in the room and on paper */
.pdeck-slide.stage .pdeck-grid.n4,.pp-sheet.paper .pdeck-slide .pdeck-grid.n4{grid-template-columns:repeat(4,minmax(0,1fr))}
/* THE MINI CARDS, CHECKED (2026-09-10, user: "double check the flex logic on the mini cards on
   the financial principles pages"). The flex itself was right; what read wrong was inherited
   from the ROOM's card: a two-line title reserve on every card whether a title wraps or not, and
   a lead figure printed at the same size as the working under it. Both are document-only fixes. */
.pp-sheet .pdoc-sec .pdoc-optcard h4{min-height:0}
.pp-sheet .pdoc-sec .pdoc-optcard .pdoc-tile-v.lead{font-size:15pt}
.pp-sheet .pdoc-opt{padding:var(--sp-2);gap:8px}
.pp-sheet .pdoc-opt h3{font-size:11pt}
.pp-sheet .pdoc-opt .pdoc-p{font-size:9pt;line-height:1.45}
.pp-sheet .pdoc-opt .pdoc-row{gap:8px;padding:6px 0}
/* a flex item will not shrink below its longest word unless it is told it may, and "Sell-through
   sensitivity" is wider than a third of the type area */
.pp-sheet .pdoc-opt .pdoc-row .cap{min-width:0}
.pp-sheet .pdoc-opt .pdoc-row-v{font-size:9.5pt;white-space:nowrap}
.pp-sheet .pdoc-opt .pdoc-tile{padding:var(--sp-2)}
.pp-sheet .pdoc-opt .pdoc-tile.big .pdoc-tile-v{font-size:14pt}
/* THE THREE TOTALS LINE UP. The cards carry a different number of rows each, so without this the
   figure the landlord is actually comparing sat at three different heights on one page. */
.pp-sheet .pdoc-opt>.pdoc-tile{margin-top:auto}
.pp-sheet .pdoc-grid-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-3)}
.pp-sheet .pdoc-grid-2>*:only-child{grid-column:1 / -1}
.pp-sheet .pdoc-tbl th,.pp-sheet .pdoc-tbl td{padding:7px 9px}
.pp-sheet .pdoc-tiles{gap:var(--sp-2)}
.pp-sheet .pdoc-tile-v{font-size:13pt}
.pp-sheet .pdoc-tile.big .pdoc-tile-v{font-size:16pt}

/* THE LOCKUP CARD TAKES THE COVER'S OPEN SPACE (2026-09-10, user: "have the open space on page 2
   have a card ... in the card that is taking up the open space goes the two logos and the x in
   between them"). One card holding both marks and the sign, GROWN by the cover's flex column
   rather than positioned, so it takes exactly the space the tiles leave and nothing is squashed.
   Replaces the 2026-09-09 prepared-for line closing the page, openly. */
.pdoc-lockup{margin-bottom:0}
/* THE CARD FILLS THE SPACE ABOVE AND BELOW (2026-09-10, user, second pass: "the card should fill
   the space above and below it"): every link in the chain stretches, and the collab row's own
   align-items:center is overridden or the card floats small in the middle of the block. */
.pdoc-cover>.pdoc-lockup.grow{flex:1 1 auto;min-height:0;display:flex}
.pdoc-cover>.pdoc-lockup.grow .pdeck-collab{flex:1 1 auto;align-self:stretch;align-items:stretch;
  max-width:none;margin-top:0}
.pdoc-cover>.pdoc-lockup.grow .pdeck-collab-card{flex:1 1 auto;width:100%;align-self:stretch;
  justify-content:center;align-items:center}

/* the cover: the tiles sit centred under the words */
.pp-sheet .pdoc-hero{display:block;border-bottom:0;padding-bottom:0}
.pp-sheet .pdoc-display{font-size:31pt;line-height:1.04}
.pp-sheet .pdoc-sub{font-size:13.5pt;margin-top:var(--sp-2)}
.pp-sheet .pdoc-lead{font-size:11pt;line-height:1.6;max-width:64ch;margin-top:var(--sp-3);
  color:rgba(16,23,43,.78)}
/* THE COVER USES ITS MEASURE (2026-09-09, user: "improve the layout of page 2"). The tile block
   was capped at 600px and centred, which left the page narrow and empty; the tiles run the full
   measure now and carry more weight, and the prepared-for line closes the page WITH the lockup
   instead of floating above a hole. */
.pdoc-sum{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-4);
  margin:var(--sp-5) 0 0}
.pdoc-sum-tile{display:flex;flex-direction:column;gap:8px;padding:var(--sp-4);
  border:1px solid rgba(16,23,43,.20);border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pdoc-sum-v{font-family:var(--font-display);font-size:20pt;line-height:1.1}
/* the prepared-for line and its rule are GONE (2026-09-10, user): the lockup card is what closes
   the cover now */

/* why a digital asset. The grid may NOT share a class with its section: `pdocSection('why', …)`
   already puts `pdoc-why` on the wrapper, and styling both turned the section itself into two
   columns with the heading stranded in the first one. */
.pdoc-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-3)}
/* THE SIX CARDS TAKE THE WHOLE PAGE (2026-09-10, user: "page 3 the cards should take the full
   page"): the grid grows to fill the section and its three rows share that space equally, so the
   sheet carries no dead band under the cards. */
.pp-sheet .pdoc-why .pdoc-cards{flex:1 1 auto;min-height:0;grid-auto-rows:1fr}
.pp-sheet .pdoc-why .pdoc-why-card{min-height:0}
.pdoc-why-card{padding:var(--sp-3);display:flex;flex-direction:column;gap:8px}
.pdoc-why-card h3{font-size:11pt;font-family:var(--font-display);text-transform:uppercase;
  letter-spacing:var(--ls-btn)}
.pdoc-why-card .pdoc-p{font-size:9.5pt;line-height:1.5}

/* THE PICTURES. Latest projects is two across and three down, taking most of the page; the site's
   own mockup runs the full width of the type area. */
.pdoc-shots{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--sp-3)}
/* FOUR FULL-WIDTH PICTURES, STACKED (2026-09-09, user, corrected the same day from five: the
   fifth clipped in his render). EQUAL GRID ROWS rather than a fixed height, so the four always
   share exactly the space above the footer band and nothing can clip whatever the head takes. */
.pp-sheet .pdoc-shots.stack{grid-template-columns:1fr;grid-template-rows:repeat(4,1fr);
  gap:var(--sp-3);flex:1 1 auto;min-height:0}
.pp-sheet .pdoc-shots.stack .pdoc-fig{min-height:0}
.pp-sheet .pdoc-shots.stack .pdoc-fig img{width:100%;height:100%;flex:1 1 auto;min-height:0;
  aspect-ratio:auto;object-fit:cover;border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pdoc-shots.two{grid-template-columns:1fr;gap:var(--sp-3)}
/* AND THE PAGE SHOWS THE SAME PICTURE, WHOLE. Cropping it here would mean the mockup checked on
   the tab is not the mockup the landlord is sent. */
.pdoc-shots.two .pdoc-fig img{aspect-ratio:auto;height:auto;max-height:330px;object-fit:contain}
.pdoc-shots .pdoc-fig img{width:100%;height:auto;aspect-ratio:16/10;object-fit:cover;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pdoc-shots.two .pdoc-fig.wide img{aspect-ratio:16/9}
.pdoc-shots.two .pdoc-fig:not(.wide) img{aspect-ratio:16/7}
.pdoc-shots .pdoc-fig figcaption{font-size:8.5pt}

/* THE SITE AND ITS MAP SIT SIDE BY SIDE ON THE PAGE (2026-08-31, user: with a map added "the page
   goes passed a4 size"). Stacked full width they took two thirds of the A4 type area between them
   and pushed the identification and hardware tables off the bottom of the sheet — AND ONLY WHEN A
   MAP WAS THERE, which is why the page looked right for as long as nobody added one.
   Two thirds to the site and one third to the map, the same split the deck's own site slide uses,
   so the two mediums say the same thing about which picture leads.
   A LONE PICTURE STILL RUNS THE FULL MEASURE: a 2:1 grid with one thing in it leaves a hole.
   NOTHING IS CROPPED TO ACHIEVE THIS. The height is capped and `object-fit:contain` letterboxes
   what does not fit, because the mockup checked on the tab has to be the mockup the landlord is
   sent — the reason `contain` was put here in the first place. The aspect ratios above are for the
   stacked, full-measure case and are released here, or a map would be forced to a 16/7 letterbox
   inside a third of the measure. */
/* THE SITE LEADS WITH THE PICTURE, FULL MEASURE (2026-09-09, user: "the site image is to take
   the full width of the page and the rest of the space is the map and the info"). This REPLACES
   the 2026-08-31 two-thirds/one-third split, openly: the mockup runs the whole measure, and the
   map and the condensed specification share the space under it. NOTHING IS CROPPED, the same
   rule as ever: capped heights and `object-fit:contain`, because the mockup checked on the tab
   is the mockup the landlord is sent. */
.pp-sheet .pdoc-site-hero{margin:0}
/* THE MOCKUP RUNS THE FULL WIDTH, NARROWING THE NO-CROP RULE OPENLY (2026-09-10, user: "the site
   image should take the full width"). `contain` letterboxed a squarer photo into the middle of
   the measure, which is what he saw. `cover` fills the width every time; only an unusually TALL
   image loses its extremes to the height cap, and a standard landscape mockup is untouched. */
.pp-sheet .pdoc-site-hero img{width:100%;height:auto;aspect-ratio:auto;max-height:460px;object-fit:cover;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
/* THE MAP GREW AND THE INFO CAME DOWN A STEP (2026-09-10, user: "make the info on page 5 a bit
   smaller and the map a bit bigger"): the map's column takes half as much again as each info
   card, and the two cards drop a type size. */
.pp-sheet .pdoc-site-under{display:grid;grid-template-columns:1fr 1fr 1.5fr;gap:var(--sp-3);
  align-items:stretch}
.pp-sheet .pdoc-site-under.nomap{grid-template-columns:1fr 1fr}
.pp-sheet .pdoc-site-map{margin:0}
.pp-sheet .pdoc-site-map img{width:100%;height:auto;aspect-ratio:auto;max-height:330px;object-fit:contain;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pp-sheet .pdoc-site-info{padding:var(--sp-2);gap:5px}
.pp-sheet .pdoc-site-info h3{font-size:9.5pt}
.pp-sheet .pdoc-site-info .pdoc-row{padding:4px 0}
.pp-sheet .pdoc-site-info .pdoc-row-v{font-size:9pt}
.pp-sheet .pdoc-site-info .cap{font-size:8.5pt}

/* the closing page */
.pdoc-thanks{display:flex;flex-direction:column;justify-content:center;flex:1 1 auto;gap:var(--sp-3)}
/* the MD's contact block on both closing pages (2026-09-11, user): name led, details quiet */
.pdoc-contact{display:flex;flex-direction:column;gap:3px;margin-top:var(--sp-2)}
.pdoc-contact-n{font-weight:700}
.pdoc-contact-l{color:var(--grey-70);font-size:var(--fs-3)}
.pp-sheet.paper .pdoc-contact-n{color:#10172B}
.pp-sheet.paper .pdoc-contact-l{color:rgba(16,23,43,.78);font-size:11pt}
.pp-sheet.paper.deckdark .pdoc-contact-n{color:#fff}
.pp-sheet.paper.deckdark .pdoc-contact-l{color:var(--grey-70)}

/* the footer is part of the page, so it is part of the print */
.pdoc-foot{display:flex;align-items:baseline;gap:12px;margin-top:auto;padding-top:var(--sp-3);
  border-top:var(--stroke) solid var(--line-08)}
.pdoc-foot .cap{font-size:8pt}
.pp-over{color:var(--warn);margin-bottom:10px}
/* the measured-fit note is information, not an alarm (2026-09-10) */
.pp-over.ok{color:var(--grey-45)}
/* the hidden measurer: laid out for real, never seen */
.pp-measure{position:absolute;left:-12000px;top:0;visibility:hidden;pointer-events:none}

/* ---- THE VISUAL DECK: THE PRESENTATION, ON WHITE PAPER (2026-08-28, user) ----
   "rework so it is visually appealing like the presentation, think the same presso but on white
   paper."

   EVERY RULE THAT GAVE THE DECK ITS SHAPE WAS SCOPED `.pdeck-slide.stage`, so the paper skin
   inherited the INK and the TYPE SIZE and no LAYOUT whatsoever: `.pdeck-grid` and `.pdeck-pics`
   were never told to be grids, so six argument cards and six photographs stacked in one column and
   ran off the bottom of the sheet, while a light slide left two thirds of the page empty with its
   words stranded at the top.

   The paper skin now carries the same SHAPE as the stage in print measure. A4 landscape is
   1123 x 794; inside the sheet's padding that is 1011 x 666, and a slide fills it exactly, so the
   builder is showing a whole page rather than the top of an unbounded one.

   PRINT IS A DIFFERENT MEDIUM, NOT A DIFFERENT THEME: white paper, EVOLV Navy ink, no glow, no
   glint, no motion. What carries over from the room is the composition. */

/* the slide fills its sheet: heading, then a growing body, then the footer on the bottom rule */
.pp-sheet.paper .pdeck-slide{min-height:0;height:100%;padding:0;gap:0;color:#10172B;
  display:flex;flex-direction:column;position:relative}
.pp-sheet.paper .pdeck-title{color:#10172B;font-size:22pt;letter-spacing:var(--ls-btn)}
/* the head row carries the rhythm AND the rule (2026-09-10): full measure, same as the foot's */
.pp-sheet.paper .pdeck-head{margin-bottom:var(--sp-3);padding-bottom:var(--sp-3);
  border-bottom:1px solid rgba(16,23,43,.14)}
/* THE BODY GROWS AND NEVER SHRINKS (2026-09-01, from his screenshot of the printed deck: the
   heading was printed across the table header and the footer across the totals).
   `flex:1 1 auto` with `min-height:0` let the body be made SHORTER than what is inside it, and it
   centres its content, so the overflow spilled BOTH WAYS — up over the heading and down over the
   footer. `flex:1 0 auto` cannot shrink: where the content is taller than the space, the body takes
   the content's height, so nothing is ever drawn on top of anything else. A page that then runs
   past the sheet is what the builder's overflow warning is for. */
.pp-sheet.paper .pdeck-body{flex:1 0 auto;display:flex;flex-direction:column;
  justify-content:center;gap:var(--sp-3)}
/* NOTHING IN THE BODY MAY BE SQUASHED UNDER ITS OWN CONTENT (2026-09-01, from his screenshot).
   A flex item shrinks by default, and `min-height:0` lets it shrink BELOW what is inside it: the
   tiles row was made shorter than the tallest tile, so that tile overflowed downward and the note
   after it was drawn straight across the tile. The table above it was squashed the same way and
   quietly lost four of its ten years.
   IT OVERFLOWS THE SHEET INSTEAD, which the builder's own overflow warning is there to say out
   loud. A page that does not fit is a thing to be told about, not to be silently compressed. */
.pp-sheet.paper .pdeck-body>*{min-height:0;flex-shrink:0}
/* A LANDSCAPE SLIDE HAS THREE TILES ACROSS IT, so an eight-figure rand value has about a third of
   the sheet to live in. The screen deck's own clamp does not apply on paper, and `--fs-8` wrapped
   it onto two lines. */
.pp-sheet.paper .pdeck-slide .pdoc-tile-v{font-size:18pt;line-height:1.15}
.pp-sheet.paper .pdeck-slide .pdoc-tile.big .pdoc-tile-v{font-size:24pt}
.pp-sheet.paper .pdeck-foot{flex:0 0 auto;color:rgba(16,23,43,.5);margin-top:var(--sp-4);
  padding-top:var(--sp-3);border-top:1px solid rgba(16,23,43,.14)}

/* ---- THE TITLE SLIDE (2026-09-10, user; REWORKED the same day: "rework the title page so
   vertically centered is the content with just the full logo on the left and then to the right
   of that aligned to top and bottom is the last screenshot of content", and the three chips are
   GONE from both title pages) ----
   The full mark on the left, the words on the right as a block whose top and bottom align to
   the mark (space-between over the mark's own height), the whole composition centred on the
   sheet and widened to the measure. No head row, no footer. */
/* the title is a positioning context for its dark ground (2026-09-11), and its own stacking
   context so the ground can sit at z-index:-1 without slipping behind the sheet */
.pdeck-slide.title{align-items:center;justify-content:center;position:relative;z-index:0}
.pdeck-slide.stage.title{flex-direction:row;gap:var(--sp-7)}
.pdeck-slide.stage.title .pdeck-tp-mark{flex:0 0 auto;display:flex;align-items:center;
  justify-content:center;
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch) 0 var(--notch) 0;
  background:rgba(255,255,255,.02);padding:56px 72px}
/* the title page's mark is FIXED (2026-09-11, user: "the one on the title page should not
   change"): the tab-2 sliders drive the corner marks and the lockup, never this plate */
.pdeck-slide.stage.title .pdoc-title-logo{height:340px;width:auto;display:block}
/* THE WORDS ARE SIZED TO THE PAGE, NOT TO LUCK (2026-09-11, from his render: the longer title
   and the landlord : address line ran straight off the page's edge and cropped the mark card
   at the other). The block takes a hard max-width so the lines WRAP, the display drops a step
   on this slide alone, and the fixed block height becomes a MINIMUM so a wrapped line grows
   the block instead of clipping inside it. */
.pdeck-slide.stage.title .pdeck-tp-text{display:flex;flex-direction:column;
  justify-content:space-between;min-height:340px;min-width:0;
  max-width:780px;gap:var(--sp-3)}
.pdeck-slide.stage.title .pdeck-display{font-size:56px;line-height:1.08}
.pdeck-slide.stage.title .pdoc-title-sub{font-family:var(--font-display);text-transform:uppercase;
  letter-spacing:var(--ls-btn);font-size:24px;color:var(--grey-70)}
.pdeck-slide.stage.title .pdeck-tp-who{font-size:22px;color:var(--grey-70)}
.pdeck-slide.stage.title .pdeck-tp-tag{font-size:var(--fs-4)}
.pp-sheet.paper .pdeck-slide.title .pdeck-body{flex-direction:row;align-items:center;
  justify-content:center;gap:var(--sp-6)}
.pp-sheet.paper .pdeck-slide.title .pdeck-tp-mark{flex:0 0 auto;display:flex;
  align-items:center;justify-content:center;
  border:var(--stroke) solid rgba(16,23,43,.16);border-radius:var(--notch) 0 var(--notch) 0;
  padding:40px 52px}
.pp-sheet.paper.deckdark .pdeck-slide.title .pdeck-tp-mark{border-color:var(--line-14);
  background:rgba(255,255,255,.02)}
.pp-sheet.paper .pdeck-slide.title .pdoc-title-logo{height:250px;width:auto;display:block}
/* the same wrap guard at print measure (2026-09-11, from his render) */
.pp-sheet.paper .pdeck-slide.title .pdeck-tp-text{display:flex;flex-direction:column;
  justify-content:space-between;min-height:250px;min-width:0;
  max-width:560px;gap:var(--sp-2)}
.pp-sheet.paper .pdeck-slide.title .pdeck-display{font-size:27pt;line-height:1.08}
.pp-sheet.paper .pdeck-slide.title .pdoc-title-sub{font-size:14pt}
.pp-sheet.paper .pdeck-slide.title .pdeck-tp-who{font-size:13pt;color:rgba(16,23,43,.78)}
.pp-sheet.paper.deckdark .pdeck-slide.title .pdeck-tp-who{color:var(--grey-70)}
.pp-sheet.paper.deckdark .pdoc-title-sub{color:var(--grey-70)}
/* THE DARK TITLE'S GROUND (2026-09-11, user, from his reference slides): the icon mark very
   faint behind the composition, cropped by the page, and a hairline above and below. The nodes
   exist only on the dark skins; the arrival stagger is switched off for them by name so the
   room's tuned animation chain is untouched. */
.pdeck-tp-bg{position:absolute;inset:0;z-index:-1;display:flex;align-items:center;
  justify-content:center;overflow:hidden;pointer-events:none}
/* THE GROUND MARK FITS THE PAGE AND ITS STRENGTH IS LOCKED (2026-09-11, user: "the bg logo is
   getting cropped at the top and bottom and then lock the opacity value as it is", superseding
   the 260% reference crop and the strength slider within the hour, both his word). The whole
   circled mark sits inside the page height, and the opacity is ONE literal here, at the value
   his slider read when he locked it. */
.pdeck-tp-bg-mark{height:100%;width:auto;opacity:.01}
.pdeck-tp-rule{position:absolute;left:6%;right:6%;height:1px;background:var(--line-14)}
.pdeck-tp-rule.t{top:15%}
.pdeck-tp-rule.b{bottom:15%}
.pdeck-slide.stage.in > .pdeck-tp-bg,.pdeck-slide.stage.in > .pdeck-tp-rule{animation:none}

/* ---- THE INTRODUCTION, THE FULL-PAGE SITE IMAGE AND THE RATE CARD (2026-09-10, from his
   reference PDF) ----
   The introduction: paragraph left, the first two project photographs stacked right. The
   full-bleed page: the mockup edge to edge, nothing else. The rate card: name, blurb,
   identification and the map left; the photograph and the specification strip right, each item
   an icon over its label over its value. Colour comes from each skin; the SHAPE is shared. */
/* the introduction's edit box on the Why EVOLV tab, in the system's own form voice: the same
   quiet field the six points use, hairline on hover, highlight on focus */
.why-intro-card{padding:var(--sp-3)}
.why-intro{width:100%;background:none;border:var(--stroke) solid transparent;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;padding:6px 8px;
  color:var(--grey-70);font-family:var(--font-body);font-size:var(--fs-3);line-height:1.6;
  min-height:150px;resize:vertical;outline:none}
.why-intro:hover{border-color:var(--line-14)}
.why-intro:focus{border-color:var(--hl)}
.pdeck-intro{display:grid;grid-template-columns:1.25fr 1fr;gap:var(--sp-5);align-items:center;
  flex:1 1 auto;min-height:0}
.pdeck-partners{display:flex;align-items:center;justify-content:space-between;
  gap:var(--sp-5);flex:0 0 auto}
.pdeck-partner{display:block;width:auto;flex:0 0 auto}
.pdeck-slide.stage .pdeck-partner{height:40px}
.pp-sheet.paper .pdeck-partner{height:26px}
/* light marks on white paper ride a navy band, never recoloured */
.pp-sheet.paper .pdeck-partners{background:#10172B;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;padding:16px 28px}
.pp-sheet.paper.deckdark .pdeck-partners{background:none;border-radius:0;padding:0}
.pdeck-intro-pics{display:flex;flex-direction:column;gap:var(--sp-3);min-height:0}
.pdeck-intro-pics .pdoc-fig{margin:0;min-height:0}
.pdeck-intro-pics .pdoc-fig img{width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pp-sheet.paper .pdeck-intro-pics .pdoc-fig img{max-height:215px}
.pdeck-slide.stage .pdeck-intro-pics .pdoc-fig img{max-height:300px}
.pdeck-slide.stage .pdeck-intro-p{font-size:var(--fs-5);line-height:1.6;max-width:none}
.pp-sheet.paper .pdeck-intro-p{font-size:12pt;line-height:1.65;max-width:none}
.pdeck-slide.full{padding:0}
.pdeck-fullimg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;
  border-radius:var(--notch) 0 var(--notch) 0}
.pdeck-slide.stage.full{min-height:844px}
.pp-sheet.paper .pdeck-slide.full .pdeck-body{position:absolute;inset:0;display:block}
.pp-sheet.paper.deckdark .pdeck-fullimg,.pp-sheet.paper .pdeck-slide.full .pdeck-fullimg{
  position:absolute;inset:0}
.pdeck-rate{display:grid;grid-template-columns:1fr 1.15fr;gap:var(--sp-5);align-items:stretch;
  flex:1 1 auto;min-height:0}
.pdeck-rate-left{display:flex;flex-direction:column;gap:var(--sp-3);min-width:0;min-height:0}
.pdeck-rate-name{font-family:var(--font-display);text-transform:uppercase;
  letter-spacing:var(--ls-display);line-height:1.05}
.pdeck-rate-rows{display:flex;flex-direction:column}
.pdeck-rate-map{margin:0;margin-top:auto;min-height:0}
.pdeck-rate-map img{width:100%;height:auto;max-height:220px;object-fit:cover;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pdeck-rate-right{display:flex;flex-direction:column;gap:var(--sp-3);min-width:0;min-height:0}
/* the photo holds close to 4:3, width leading (2026-09-10, user) */
.pdeck-rate-photo{margin:0;min-height:0;flex:0 0 auto}
.pdeck-rate-photo img{width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pdeck-rate-strip{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:var(--sp-2)}
.pdeck-rate-item{display:flex;flex-direction:column;align-items:center;text-align:center;gap:7px;
  min-width:0}
/* matched to his reference (2026-09-10): a bare icon over a short rule over the label, and the
   label keeps two lines' worth of room so every VALUE sits on one line across the strip */
.pdeck-rate-item .why-ico{background:none;border:0;border-radius:0;width:auto;height:auto;
  padding-bottom:9px;border-bottom:1px solid var(--line-22)}
.pdeck-rate-item .cap{font-size:8pt;letter-spacing:.06em;text-transform:uppercase;
  min-height:3em;display:flex;align-items:flex-start;justify-content:center}
.pdeck-rate-v{font-family:var(--font-display);white-space:nowrap}
.pp-sheet.paper .pdeck-rate-item .why-ico{background:none;border:0;border-radius:0;
  border-bottom:1px solid rgba(16,23,43,.3);width:auto;height:auto;padding-bottom:8px}
.pp-sheet.paper.deckdark .pdeck-rate-item .why-ico{border-bottom-color:var(--line-22);
  background:none}
/* the rate card at each skin's measure */
/* the hero name came down a step with its own 10px of air (2026-09-10, user) */
.pdeck-rate-name{margin-top:10px}
.pdeck-slide.stage .pdeck-rate-name{font-size:48px;color:#fff}
.pdeck-slide.stage .pdeck-rate-blurb{max-width:none}
.pdeck-slide.stage .pdeck-rate-v{font-size:22px;color:#fff}
.pdeck-slide.stage .pdeck-rate-item .why-ico{width:44px;height:44px;
  border-color:var(--line-14);background:rgba(255,255,255,.03)}
.pdeck-slide.stage .pdeck-rate-item .why-ico .sec-icon{width:30px;height:30px;color:var(--hl);opacity:1}
.pdeck-slide.stage .pdeck-rate-map img{max-height:250px}
.pp-sheet.paper .pdeck-rate-name{font-size:26pt;color:#10172B}
.pp-sheet.paper .pdeck-rate-v{font-size:12.5pt}
.pp-sheet.paper .pdeck-rate-item .why-ico .sec-icon{width:22px;height:22px}
.pp-sheet.paper.deckdark .pdeck-rate-name{color:#fff}
.pp-sheet.paper.deckdark .pdeck-rate-v{color:#fff}
/* THE FORECAST FITS ITS SHEET (2026-09-10, user: "page 10 and 12 are overlapping scale to fit
   page"): the 8-row pages ran past A4 and bled into the pages after them, so the forecast slides
   print a step tighter — rows, tiles and gaps, never the content. */
.pp-sheet.paper .pdeck-slide.forecast .pdeck-body{gap:var(--sp-2);justify-content:flex-start}
/* ONE OPTION PER PAGE (2026-09-10, user): the whole term prints on one sheet, so the rows are a
   step tighter again — ten years, the tiles and the note inside the fixed box */
.pp-sheet.paper .pdeck-slide.forecast .pdoc-tbl th,
.pp-sheet.paper .pdeck-slide.forecast .pdoc-tbl td{padding:5px 10px}
.pp-sheet.paper .pdeck-slide.forecast .pdoc-tbl{font-size:9.5pt}
.pp-sheet.paper .pdeck-slide.forecast .pdoc-tbl th{font-size:8pt}
.pp-sheet.paper .pdeck-slide.forecast .pdoc-tile{padding:var(--sp-2) var(--sp-3)}
.pp-sheet.paper .pdeck-slide.forecast .pdoc-tile.big .pdoc-tile-v{font-size:18pt}
.pp-sheet.paper .pdeck-slide.forecast .cap{font-size:8.5pt}

/* the cover and the closing page: one idea, held in the middle of the sheet */
/* THE DISPLAY LINE IS MODERNIZ, ON PAPER AS IN THE ROOM (2026-08-28, user: "the first and last page
   of visual deck fonts"). It was set in Cera when the paper skin was written, so the cover and the
   closing page came out in body type while the same slides presented in Moderniz uppercase.
   PRINT IS A DIFFERENT MEDIUM, NOT A DIFFERENT TYPEFACE: what changes on paper is the ink and the
   measure. Moderniz for headings is the CI and it does not have a print exception. */
.pp-sheet.paper .pdeck-display{color:#10172B;font-size:34pt;line-height:1.04;
  font-family:var(--font-display);text-transform:uppercase;letter-spacing:var(--ls-display)}
/* the same left-aligned row at print measure, inside the paper body box */
.pp-sheet.paper .pdeck-slide.cover .pdeck-body{display:flex;flex-direction:column;
  align-items:flex-start;justify-content:center;gap:var(--sp-3)}
.pp-sheet.paper .pdeck-slide.cover .pdeck-display{max-width:640px;text-align:left}
.pp-sheet.paper .pdeck-slide.cover .pdeck-tag{text-align:left}
.pp-sheet.paper .pdeck-slide.cover .pdeck-cv-row{margin-top:var(--sp-3)}
.pp-sheet.paper .pdeck-cv-figs{border-color:rgba(16,23,43,.2);padding:36px 44px;gap:8px}
.pp-sheet.paper.deckdark .pdeck-cv-figs{border-color:var(--line-14)}
.pp-sheet.paper .pdeck-slide.cover .pdeck-collab{margin-top:0}
.pp-sheet.paper .pdeck-slide.cover .pdeck-collab-card{padding:44px 52px}
.pp-sheet.paper .pdeck-slide.cover .pdeck-collab .pdeck-evolv{height:calc(62px*var(--evsc,1));
  max-height:calc(62px*var(--evsc,1))}
.pp-sheet.paper .pdeck-slide.cover .pdoc-p{font-size:12.5pt;line-height:1.6;max-width:62ch;
  margin-top:var(--sp-2)}
.pp-sheet.paper .pdeck-slide.cover .cap{margin-top:var(--sp-3)}

/* the one big figure. It is the whole point of the page, so it gets the room */
/* AND SO IS THE ONE BIG FIGURE, for the same reason and from the same edit: the room sets it in
   Moderniz and the printed page was setting it in Cera. */
.pp-sheet.paper .pdeck-big{color:#10172B;font-size:52pt;line-height:1;
  font-family:var(--font-display);letter-spacing:var(--ls-display)}
/* the cover's figure steps below its 34pt display line on paper too (2026-09-23, user) */
.pp-sheet.paper .pdeck-slide.cover .pdeck-big{font-size:27pt}
.pp-sheet.paper .pdeck-slide .pdoc-p{font-size:11.5pt;line-height:1.6;max-width:74ch;
  color:rgba(16,23,43,.78)}

/* THE ARGUMENT, THREE ACROSS AND TWO DOWN, as it stands in the room */
.pp-sheet.paper .pdeck-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--sp-3);align-content:center}
.pp-sheet.paper .pdeck-slide.spec .pdeck-grid{grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--sp-6);width:92%;align-self:center}
.pp-sheet.paper .pdeck-item{display:flex;flex-direction:column;gap:9px;padding:var(--sp-3);
  background:#FFFFFF;border:1px solid rgba(16,23,43,.22);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pp-sheet.paper .pdeck-slide.spec .pdeck-item{border:0;padding:0 24px;gap:0}
.pp-sheet.paper .pdeck-item h4{color:#10172B;font-size:11.5pt;font-family:var(--font-display);
  text-transform:uppercase;letter-spacing:var(--ls-btn);line-height:1.18}
.pp-sheet.paper .pdeck-item .cap{font-size:9pt;line-height:1.5;color:rgba(16,23,43,.7)}
.pp-sheet.paper .pdeck-item .why-ico{width:36px;height:36px;flex:0 0 auto;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pp-sheet.paper .pdeck-item .why-ico .sec-icon{width:18px;height:18px;color:#10172B;opacity:1}

/* THE PICTURES FILL THE PAGE. Three across and two down for the projects, each cropped to a
   common shape so the grid reads as one block. */
.pp-sheet.paper .pdeck-pics{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  grid-auto-rows:1fr;gap:var(--sp-3);flex:1 1 auto;min-height:0}
.pp-sheet.paper .pdeck-pics .pdoc-fig{display:flex;flex-direction:column;gap:6px;min-height:0}
.pp-sheet.paper .pdeck-pics .pdoc-fig img{width:100%;height:auto;flex:1 1 auto;min-height:0;
  aspect-ratio:auto;object-fit:cover;border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.pp-sheet.paper .pdeck-pics .pdoc-fig figcaption{flex:0 0 auto;font-size:8pt}

/* THE SITE IS TWO THIRDS AND THE MAP ONE THIRD (2026-08-28, user), and NEITHER IS CROPPED: the
   mockup checked on the tab has to be the mockup the landlord is handed. */
.pp-sheet.paper .pdeck-pics.site{grid-template-columns:2fr 1fr;grid-auto-rows:auto;
  align-items:start;flex:0 1 auto;gap:var(--sp-4)}
.pp-sheet.paper .pdeck-pics.site .pdoc-fig img{height:auto;flex:0 0 auto;max-height:400px;
  object-fit:contain}
.pp-sheet.paper .pdeck-pics.site .pdoc-fig:only-child img{max-height:440px}

/* the tables and the tiles read from a metre away, not from a desk */
.pp-sheet.paper .pdeck-slide .pdoc-tbl{font-size:11pt}
.pp-sheet.paper .pdeck-slide .pdoc-tbl th{font-size:8.5pt}
.pp-sheet.paper .pdeck-slide .pdoc-tbl th,
.pp-sheet.paper .pdeck-slide .pdoc-tbl td{padding:10px 12px}
.pp-sheet.paper .pdeck-slide .pdoc-tiles{gap:var(--sp-3);margin:0}
.pp-sheet.paper .pdeck-slide .pdoc-tile{padding:var(--sp-4)}
.pp-sheet.paper .pdeck-slide .pdoc-tile-v{font-size:21pt}
.pp-sheet.paper .pdeck-slide .pdoc-tile.big .pdoc-tile-v{font-size:27pt}
.pp-sheet.paper .pdeck-slide .pdoc-formula{font-size:12pt;padding:var(--sp-3) var(--sp-4)}
.pp-sheet.paper .pdeck-slide .pdoc-row{padding:9px 0}
.pp-sheet.paper .pdeck-slide .pdoc-row-v{font-size:11.5pt}

/* ---- THE MODERNIZ INK COMES DOWN ON THE PRINTABLES (2026-09-10, user) ----
   "the general contrast of the presentation is too hectic the moderniz font reads as too heavy so
   make the cards have a marginally heavier stroke ... and then we need to decide on a lighter
   color for the moderniz font." ONE TOKEN, `--paper-head`, read by every display-font element on
   the printed page, document and visual deck both, so the two cannot drift; the dark deck swaps
   the token further down. The 2026-09-09 small-text strengths are untouched: the complaint was
   the HEADINGS, not the captions, and this NARROWS that round rather than reversing it.
   Declared AFTER every #10172B heading rule above, at equal or higher specificity, so order wins. */
.pp-sheet.paper{--paper-head:rgba(16,23,43,.84)}
.pp-sheet.paper h2,.pp-sheet.paper h3,.pp-sheet.paper .pdoc-display,.pp-sheet.paper .pdoc-sub,
.pp-sheet.paper .pdoc-sum-v,.pp-sheet.paper .pdoc-tile-v,.pp-sheet.paper .pdeck-title,
.pp-sheet.paper .pdeck-display,.pp-sheet.paper .pdeck-big,.pp-sheet.paper .pdeck-item h4,
.pp-sheet.paper .pdoc-why-card h3{color:var(--paper-head)}
/* and the card outline comes up a step as the ink comes down */
.pp-sheet.paper .card,.pp-sheet.paper .pdeck-item,.pp-sheet.paper .pdoc-sum-tile,
.pp-sheet.paper .pdoc-tile,.pp-sheet.paper .pdoc-formula,.pp-sheet.paper .pdeck-logo-card{
  border-width:1.5px}

/* ---- THE LANDLORD'S MARK (2026-08-28, user) ----
   "have the option when the logo is uploaded to place it on a card background with the color of
   the card so the logo can always be clear to see and read, the card should follow the shape of
   our other cards in the system."

   THE CARD IS A REAL E.V.O.S. CARD: the CI cut-frame (rounded top-left and bottom-right, sharp
   top-right and bottom-left) with its hairline. Its FILL comes from the measured tone rather than
   from the surface, because a card in the surface's own colour does not make a mark readable — a
   black logo on our Depth Navy card is exactly as lost as it was on the ground behind it. A pale
   mark gets the dark card, a dark mark gets the light one, and one that reads either way takes the
   surface it is on. THE MARK ITSELF IS NEVER RECOLOURED. */
.pdeck-logo-card{display:inline-flex;align-items:center;justify-content:center;
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;border:var(--stroke) solid var(--line-14)}

/* ---- THE HEAD ROW AND THE FOOTER MARK (2026-09-10, user, his third word on the geometry:
   "swap the logos so the other company is top right and the evolv is on the bottom right and
   then make sure the divider lines are the same length") ----
   The TITLE sits left and the LANDLORD'S card right in one head row; EVOLV's wordmark (the TYPE
   file, the only mark readable at footer height) signs the right end of the footer band, on a
   small navy plate on white paper because THE MARK IS NEVER RECOLOURED. The head row itself
   carries the rule, so the head and foot dividers run the same full measure. Everything is IN
   FLOW; the cover and the bare pages carry neither.
   SIZED, NEVER INFERRED (2026-08-28): every mark carries an explicit height with width:auto, and
   the landlord's is still capped by --pdeck-mark-w because its shape is unknown. */
.pdeck-head{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);
  flex:0 0 auto}
.pdeck-head .pdeck-title{flex:1 1 auto;min-width:0}
.pdeck-head .pdeck-logo-card{position:static;flex:0 0 auto}
.pdeck-foot{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4)}
.pdeck-foot .pdeck-foot-t{flex:1 1 auto;min-width:0}
/* THE TWO CORNER MARKS SHARE ONE WIDTH (2026-09-10, user: "ensure the added logo and our logo
   are aligned to width"): the landlord's head card and EVOLV's foot mark sit in boxes of the
   same width, centred, so the page's right column reads as one. The plate died with the type
   file: the full blue mark reads on white paper. */
.pdeck-foot .pdeck-evolv-foot{display:block;width:auto;flex:0 0 auto}
.pdeck-head .pdeck-logo-card,.pdeck-foot .pdeck-evolv-box{width:var(--pdeck-corner-w);
  justify-content:center}
.pdeck-foot .pdeck-evolv-box{display:flex;align-items:center;flex:0 0 auto}
/* in the room */
.pdeck-slide.stage{--pdeck-corner-w:150px}
.pdeck-slide.stage .pdeck-head .pdeck-logo-card{padding:8px 12px}
/* the corner marks take the tab-2 size sliders (2026-09-11, user: they "should control the
   other instances of the logo used in the footer/header"); the corner BOX keeps its one width
   so the page's right column still reads as one, and max-width holds a scaled mark inside it */
.pdeck-slide.stage .pdeck-head .pdeck-logo{position:static;
  height:calc(40px*var(--llsc,1));width:auto;max-width:100%;object-fit:contain}
.pdeck-slide.stage .pdeck-foot .pdeck-evolv-foot{height:calc(60px*var(--evsc,1))}
/* on paper */
.pp-sheet.paper .pdeck-head .pdeck-logo-card{padding:5px 8px}
.pp-sheet.paper .pdeck-head .pdeck-logo{position:static;
  height:calc(26px*var(--llsc,1));width:auto;max-width:100%;object-fit:contain}
.pp-sheet.paper .pdeck-foot .pdeck-evolv-foot{height:calc(40px*var(--evsc,1))}
.pp-sheet.paper .pdeck-slide{--pdeck-corner-w:100px}

/* ---- THE SIX CARD FILLS (2026-09-10, user) ----
   "give options of the evolv colors to put as the bg of the card white black and the 3 others
   and an empty card with just the stroke." The brand's own five values and the empty frame, no
   new hues, on every ground the card is drawn on. The fills are OPAQUE, so the 2026-08-19
   tint-compositing rule has nothing to composite; the person chooses against their own mark and
   the measurement still only picks the default. THE MARK ITSELF IS NEVER RECOLOURED.
   The empty card is the frame and its hairline and nothing else, and `background:none` is doing
   real work in the room, where the base card rule would otherwise leave a tint behind it. */
.pdeck-slide.stage .pdeck-logo-card.card-empty{background:none;border-color:var(--line-14)}
.pdeck-slide.stage .pdeck-logo-card.card-white{background:#FFFFFF;border-color:rgba(16,23,43,.14)}
.pdeck-slide.stage .pdeck-logo-card.card-grey{background:#E0E0DF;border-color:rgba(16,23,43,.14)}
.pdeck-slide.stage .pdeck-logo-card.card-navy{background:#10172B;border-color:var(--line-22)}
.pdeck-slide.stage .pdeck-logo-card.card-depth{background:#12284C;border-color:var(--line-22)}
.pdeck-slide.stage .pdeck-logo-card.card-black{background:#000000;border-color:var(--line-22)}

/* THE COVER CARRIES THE COLLABORATION (2026-08-28, user): the landlord's mark, a multiplication
   sign, then EVOLV Outdoor. Both marks are in the FLOW here and sized to each other, so neither
   reads as the header of the other. */
/* NEVER WRAPS. Two marks and a sign are ONE object: broken over two lines the x reads as a
   bullet and the second mark reads as a caption of the first, which is exactly what happened.
   THE MARKS ARE SIZED BY HEIGHT AND THE HEIGHT IS THE SAME FOR BOTH, so neither outranks the
   other however differently shaped their files are. EVOLV's own mark is TALL (576 x 829, the
   icon over the wordmark), so a height that suits a wide landlord logo leaves it about 40px
   across and unreadable: the row is set from the height both can carry. */
/* THE WHOLE LOCKUP IS ONE CARD (2026-09-10, user): both marks and the sign inside a single
   `pdeck-collab-card`, whose fill is the chosen card option, so the six fills drive the cover
   too. On a dark fill the sign lightens with the marks. */
.pdeck-collab{display:flex;align-items:center;flex-wrap:nowrap;align-self:flex-start;
  max-width:100%}
.pdeck-collab-card{display:inline-flex;align-items:center;justify-content:center;flex-wrap:nowrap}
.pdeck-collab-x{font-family:var(--font-display);line-height:1;flex:0 0 auto}
.pdeck-evolv{display:block;flex:0 0 auto;width:auto}
.pdeck-collab-card.card-navy .pdeck-collab-x,.pdeck-collab-card.card-depth .pdeck-collab-x,
.pdeck-collab-card.card-black .pdeck-collab-x{color:rgba(255,255,255,.6)}

/* BALANCED BY EYE, NOT BY THE SAME NUMBER (2026-08-28, user: "visually balance them"). Setting
   both marks to one height is the obvious thing and it is wrong here: EVOLV's own mark is STACKED,
   and its wordmark is only the bottom 197 of its 829 box — under a quarter of it. Matched heights
   therefore render OUR name at about a quarter the size of the landlord's, which is what the
   screenshot showed. The stacked mark is given the greater height so the two read as equals.

   AND THE LANDLORD'S IS CAPPED BOTH WAYS, because its shape is unknown: a wide wordmark is held by
   the width, a tall or square one by the height, so no logo anyone uploads can dominate the row. */

/* in the room, at room size. Scaled up a step (2026-09-10, user: "slightly scale up") */
.pdeck-slide.stage .pdeck-collab{margin-top:var(--sp-5)}
.pdeck-slide.stage .pdeck-collab-card{gap:var(--sp-5);padding:30px 40px}
.pdeck-slide.stage .pdeck-collab .pdeck-logo{position:static;margin-top:0;flex:0 0 auto;
  height:calc(100px*var(--llsc,1));width:auto;max-width:calc(280px*var(--llsc,1));object-fit:contain}
.pdeck-slide.stage .pdeck-collab .pdeck-evolv{height:calc(146px*var(--evsc,1));
  max-height:calc(146px*var(--evsc,1));width:auto}
.pdeck-slide.stage .pdeck-collab-x{font-size:2.6rem;color:var(--grey-45);opacity:.65}

/* on paper, at print measure, the same step up */
.pp-sheet.paper .pdeck-collab{margin-top:var(--sp-4)}
.pp-sheet.paper .pdeck-collab-card{gap:var(--sp-4);padding:22px 30px}
.pp-sheet.paper .pdeck-collab .pdeck-logo{position:static;margin-top:0;flex:0 0 auto;
  height:calc(62px*var(--llsc,1));width:auto;max-width:calc(180px*var(--llsc,1));object-fit:contain}
.pp-sheet.paper .pdeck-collab .pdeck-evolv{height:calc(92px*var(--evsc,1));
  max-height:calc(92px*var(--evsc,1));width:auto}
/* EVOLV ALONE IS COMPOSED, NOT STRANDED (2026-09-09, user), and the chosen fill still paints the
   card: with no landlord mark the card holds EVOLV large, no sign, nothing paired with it. */
.pp-sheet.paper .pdeck-collab.solo{justify-content:flex-start}
.pp-sheet.paper .pdeck-collab.solo .pdeck-evolv{height:calc(124px*var(--evsc,1));
  max-height:calc(124px*var(--evsc,1))}
.pp-sheet.paper .pdeck-collab.solo .pdeck-collab-card{padding:24px 36px}
.pp-sheet.paper .pdeck-collab-x{font-size:20pt;color:rgba(16,23,43,.45)}

/* the six fills on paper: the dark three carry their own edge, the light three the printed
   hairline, and the empty one is the sheet itself behind the marks */
.pp-sheet.paper .pdeck-logo-card.card-empty{background:none;border-color:rgba(16,23,43,.16)}
.pp-sheet.paper .pdeck-logo-card.card-white{background:#FFFFFF;border-color:rgba(16,23,43,.16)}
.pp-sheet.paper .pdeck-logo-card.card-grey{background:#E0E0DF;border-color:rgba(16,23,43,.16)}
.pp-sheet.paper .pdeck-logo-card.card-navy{background:#10172B;border-color:#10172B}
.pp-sheet.paper .pdeck-logo-card.card-depth{background:#12284C;border-color:#12284C}
.pp-sheet.paper .pdeck-logo-card.card-black{background:#000000;border-color:#000000}
/* presenting shows the same pages, so the room sees what the landlord will be sent */
.pdeck.paper{background:#FFFFFF}
.pdeck.paper .pdeck-bar .iconbtn,.pdeck.paper .pdeck-bar .lbl{color:#10172B}
.pdeck.paper .pdeck-stage{color:#10172B}
.pdeck.paper .pdeck-slide{max-width:1180px;padding:var(--sp-4) 0}
.pdeck.paper .pdeck-title{color:#10172B;padding-bottom:12px;
  border-bottom:1px solid rgba(16,23,43,.14)}
.pdeck.paper .pdeck-display,.pdeck.paper .pdeck-big,.pdeck.paper .pdeck-item h4{color:#10172B}
.pdeck.paper .cap{text-transform:none;letter-spacing:0;color:rgba(16,23,43,.6)}
.pdeck.paper .pdoc-tbl th{color:rgba(16,23,43,.55);border-color:rgba(16,23,43,.2)}
.pdeck.paper .pdoc-tbl td{color:rgba(16,23,43,.8);border-color:rgba(16,23,43,.1)}
.pdeck.paper .pdoc-tile,.pdeck.paper .pdoc-formula{background:#F4F6FA;
  border-color:rgba(16,23,43,.1);color:#10172B}
.pdeck.paper .pdoc-tile-v{color:#10172B}

/* ---- THE DARK DECK (2026-09-10, user) ----
   "on the visual deck i would like a button that selects dark or light mode and the pdf exports
   as such." COLOUR ONLY: every layout rule above is shared, per the 2026-08-28 rule that a layout
   scoped to one skin is not a shared definition. The ground is near-black, the ink white, the
   heading token swaps, and the marks follow the medium (`propSlideNode` hands the dark flag to
   the logo pickers, so EVOLV prints white-full here). `print-color-adjust:exact` is what makes
   the dark ground actually reach the PDF. */
/* EXACTLY THE ROOM, ON A SHEET (2026-09-10, user: "the dark mode is to look exactly like the
   present mode with gradients etc"). Every value below is the STAGE's own: the ambient Depth
   Navy glows become a static background on the sheet (a print cannot drift, so the deckDrift
   animation is the one thing that does not carry), the cards take the room's lit surface, the
   tables the room's inks, and the type tokens are the room's greys. */
.pp-sheet.paper.deckdark{--paper-head:#FFFFFF;color:#fff;border-color:#10172B;
  background:
    radial-gradient(46% 38% at 18% 22%, rgba(18,40,76,.55), transparent 70%),
    radial-gradient(40% 34% at 82% 74%, rgba(18,40,76,.42), transparent 70%),
    #0A0A0A;
  -webkit-print-color-adjust:exact;print-color-adjust:exact}
.pp-sheet.paper.deckdark .pdeck-slide{color:#fff}
.pp-sheet.paper.deckdark .pdeck-title{color:#fff}
.pp-sheet.paper.deckdark .pdeck-head{border-bottom-color:var(--line-14)}
/* the icons follow the mode (2026-09-10, user: "the dark mode does not show them as light
   icons"): the light skin's five-class why-ico rule outranked the dark override, so the dark one
   matches it at its own strength */
.pp-sheet.paper.deckdark .pdeck-item .why-ico .sec-icon,
.pp-sheet.paper.deckdark .pdeck-rate-item .why-ico .sec-icon{color:var(--hl);opacity:1}
.pp-sheet.paper.deckdark .pdeck-display,.pp-sheet.paper.deckdark .pdeck-big{color:#fff}
.pp-sheet.paper.deckdark .pdeck-tag{color:var(--grey-70)}
.pp-sheet.paper.deckdark .cap{color:var(--grey-45)}
.pp-sheet.paper.deckdark .pdoc-p,
.pp-sheet.paper.deckdark .pdeck-slide .pdoc-p{color:var(--grey-70)}
.pp-sheet.paper.deckdark strong{color:#fff}
.pp-sheet.paper.deckdark .pdeck-item{background:rgba(255,255,255,.02);border-color:var(--line-14)}
.pp-sheet.paper.deckdark .pdeck-item h4{color:#fff}
.pp-sheet.paper.deckdark .pdeck-item .cap{color:var(--grey-45)}
.pp-sheet.paper.deckdark .why-ico{background:rgba(255,255,255,.03);border-color:var(--line-14)}
.pp-sheet.paper.deckdark .sec-icon{color:var(--hl);opacity:1}
.pp-sheet.paper.deckdark .pdoc-tbl th{color:var(--grey-45);border-color:var(--line-14)}
.pp-sheet.paper.deckdark .pdoc-tbl td{color:var(--grey-70);border-color:var(--line-08)}
.pp-sheet.paper.deckdark .pdoc-tbl td:first-child{color:#fff}
.pp-sheet.paper.deckdark .pdoc-tile,.pp-sheet.paper.deckdark .pdoc-sum-tile,
.pp-sheet.paper.deckdark .pdoc-formula{background:rgba(255,255,255,.02);
  border-color:var(--line-14);color:#fff}
.pp-sheet.paper.deckdark .pdoc-tile-v{color:#fff}
.pp-sheet.paper.deckdark .pdoc-optcard .pdoc-tile-v.lead{color:#fff}
.pp-sheet.paper.deckdark .pdoc-row{border-color:var(--line-08)}
.pp-sheet.paper.deckdark .pdoc-row-v{color:#fff}
.pp-sheet.paper.deckdark .pdeck-foot{color:var(--grey-22);border-top-color:var(--line-14)}
.pp-sheet.paper.deckdark .pdoc-fig figcaption{color:var(--grey-45)}
.pp-sheet.paper.deckdark .pdoc-fig img{border:var(--stroke) solid var(--line-14)}
.pp-sheet.paper.deckdark .pdeck-logo-card.card-empty{border-color:var(--line-22)}
.pp-sheet.paper.deckdark .pdeck-collab-x{color:var(--grey-45)}

@media print{
  html{color-scheme:light}
  /* EVERYTHING THAT IS NOT THE PRINT BOX IS HIDDEN, STRUCTURALLY (2026-09-11, user: the black
     portrait page survived the named-page fix). The old rule ENUMERATED what to hide, and the
     `.bg` glow layer — fixed, full-viewport, black, the FIRST child of the body — was never on
     the list, so it printed a leading portrait page in the default page context. A list has to
     be remembered every time a body child is added; this selector cannot be: any body child
     that is not the print box stays off the paper, including ones that do not exist yet. */
  body.pdoc-printing>:not(.pp-print){display:none!important}
  body.pdoc-printing .no-print{display:none!important}
  body.pdoc-printing .pp-print{display:block}
  /* ONE SHEET, ONE PAGE. The box is the same one the builder drew, so nothing repaginates here. */
  .pp-print .pp-sheet{break-after:page;page-break-after:always;box-shadow:none;border:0;margin:0}
  .pp-print .pp-sheet:last-child{break-after:auto;page-break-after:auto}
  .pdoc-tbl thead{display:table-header-group}
  .pdoc-tbl tr{break-inside:avoid;page-break-inside:avoid}
  /* THE VISUAL DECK PRINTS ON LANDSCAPE PAPER (2026-08-28, user). `pdoc-landscape` was being put
     on the body and NOTHING READ IT: two empty rules stood where the rule should have been, so a
     1123 x 794 sheet was sent to a portrait A4 and came out shrunk with a band of white beside it.
     `@page` cannot be narrowed by a body class, so the size lives on a NAMED page and the sheets
     of a landscape run are assigned to it. Where named pages are not supported the run falls back
     to portrait, which is exactly where it stood before. */
  @page{size:A4 portrait;margin:0}
  @page evosLandscape{size:A4 landscape;margin:0}
  /* THE CONTAINER JOINS THE NAMED PAGE (2026-09-11, user: "there is a black portrait first
     page that needs to go"). With the name on the SHEETS alone, the initial page box is
     created in the DEFAULT portrait context and Chrome breaks to the named page after it: a
     leading portrait page, painted with the body's own dark ground. Naming the container too
     starts the run inside the landscape context, so no default page exists to lead with; and
     the printing body is painted white so no stray page can ever come out black. */
  body.pdoc-landscape .pp-print,
  body.pdoc-landscape .pp-print .pp-sheet{page:evosLandscape}
  body.pdoc-printing{background:#fff}
}
.sd-warn .pw-row{cursor:pointer}
.sd-warn .pw-row.sd-expired{border-color:var(--bad)}

/* THE DOCUMENT RUNS THE WHOLE WIDTH (2026-08-27, carried over from the tool's own rule). A
   proposal is a document, not a section, so `.wrap`'s column cap is released while one is open.
   The printing guard that used to live here went with the tool: the three print paths are
   E.V.O.S.'s own now and their rules sit with the rest of the document's CSS. */
/* THE BUILDER IS WIDE, NOT EDGE TO EDGE (2026-08-27, user). The width cap comes off so the page
   and its rail have room, but the gutter stays: `--pad-x` is the system's horizontal padding and
   the builder is a screen like any other. Dropping it was left over from the old landlord tool,
   which really was a document running the full bleed. */
body.pdoc-open main.wrap{max-width:none}

/* ---------- Sites: the pipeline, as the summary ----------
   Replaces five disconnected totals (2026-08-24, user). Seven stages in order, so the shape of the
   work and where it is stuck are one picture. Line-based and cut-frame like everything else; the
   only colour is the Site Development department accent on the steps that actually hold something,
   which is the sanctioned exception rather than a new hue. */
.sd-flow-card{padding:var(--sp-4) var(--sp-3)}
.sd-flow{display:flex;align-items:stretch;gap:0;flex-wrap:wrap}
/* THE STAGES ARE TABS (2026-08-28, user: "use tab logic"), so each one is a real button: the font
   and colour are reset off it because a <button> inherits neither, and the cursor says it responds
   whether or not anything is sitting at it. */
.sd-flow .sd-step{display:block;flex:1 1 96px;min-width:96px;padding:var(--sp-2) var(--sp-2);text-align:center;
  border:var(--stroke) solid transparent;border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  font:inherit;color:inherit;background:none;cursor:pointer;
  transition:border-color var(--t-micro) var(--ease),background var(--t-micro) var(--ease)}
/* A STAGE READS AS PRESSABLE BEFORE IT IS PRESSED (2026-09-28, user: "no hover state ...
   navigating to the proposals is not easy to figure out"). The old hover was --line-14, the
   same value as the chosen tab's border, so it was invisible in practice. The hover now lifts
   the ground and lights the label, the same affordance the nav tabs carry. */
.sd-flow .sd-step:hover{border-color:var(--line-40);background:rgba(255,255,255,.04)}
.sd-flow .sd-step:hover .sd-step-l{color:#fff}
.sd-flow .sd-step:hover .sd-step-n{color:var(--grey-70)}
/* EMPTY IS QUIET, OCCUPIED IS LIT. Reading the row should be finding the lit ones, not counting. */
.sd-flow .sd-step-n{font-family:var(--font-display);font-size:var(--fs-6);line-height:1;color:var(--grey-45)}
.sd-flow .sd-step-l{font-family:var(--font-display);text-transform:uppercase;font-size:var(--fs-2);
  letter-spacing:var(--ls-btn);color:var(--grey-45);margin-top:var(--sp-1)}
.sd-flow .sd-step-s{font-size:var(--fs-1);color:var(--grey-22);margin-top:2px;line-height:1.3}
.sd-flow .sd-step.on{border-color:var(--line-14);background:var(--depth-22)}
.sd-flow .sd-step.on .sd-step-n{color:var(--dept-sitedev)}
.sd-flow .sd-step.on .sd-step-l{color:#fff}
.sd-flow .sd-step.on .sd-step-s{color:var(--grey-45)}
.sd-flow .sd-step.done.on .sd-step-n{color:var(--ok)}
/* THE ONE BEING READ. Distinct from `.on`, which means "something is sitting here": a stage can be
   occupied without being the one you are looking at, and empty while being exactly that. */
.sd-flow .sd-step.active{border-color:var(--hl);background:var(--depth-22)}
.sd-flow .sd-step.active .sd-step-l{color:#fff}
.sd-flow .sd-step.active .sd-step-n{color:#fff}
.sd-flow .sd-step.active .sd-step-s{color:var(--grey-45)}
.sd-flow .sd-step.active.on .sd-step-n{color:var(--dept-sitedev)}
.sd-flow .sd-step.done.active.on .sd-step-n{color:var(--ok)}

/* the run of the pipeline, drawn rather than implied */
.sd-flow .sd-step-link{flex:0 0 auto;align-self:center;width:var(--sp-3);height:var(--stroke);
  background:var(--line-08)}

/* WHAT IS SITTING AT THE STAGE BEING READ. One panel, under the strip, always saying something. */
.sd-at{margin-top:var(--sp-3);padding:var(--sp-4)}
.sd-at-head{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
  padding-bottom:var(--sp-3);margin-bottom:var(--sp-2);
  border-bottom:var(--stroke) solid var(--line-08)}
.sd-at-row{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:var(--sp-3) 0}
.sd-at-row + .sd-at-row{border-top:var(--stroke) solid var(--line-08)}
.sd-at-main{min-width:0;display:flex;flex-direction:column;gap:3px}
.sd-at-n{color:#fff;font-size:var(--fs-4)}

.sd-facts{margin-top:var(--sp-2)}
@media (max-width:900px){
  .sd-flow .sd-step{flex:1 1 40%}
  .sd-flow .sd-step-link{display:none}
}

/* the deal's own progress line: what happens next, and whose move it is */
.dm-next{margin-top:var(--sp-2);color:var(--grey)}
.dm-declined{margin-top:var(--sp-1);color:var(--bad)}

/* ---------- Admin · roles and permissions (2026-08-25) ----------
   Reuses the collapsible `.ll-card` from the landlord book: a role and a landlord are the same
   shape on screen, a named thing with rows folded underneath it. Only the rows are new. */
.perm-sub{font-size:var(--fs-4);color:var(--grey-45);margin:var(--sp-4) 0 var(--sp-2)}
.perm-levels{display:flex;flex-direction:column;gap:8px}
.perm-level{padding:14px 18px;display:flex;flex-direction:column;gap:6px}
.perm-level-h{display:flex;align-items:center;gap:10px}
.perm-roles{display:flex;flex-direction:column;gap:8px}
.perm-row{display:flex;align-items:center;gap:14px;padding:7px 0;
  border-bottom:var(--stroke) solid var(--line-08)}
.perm-row:last-child{border-bottom:0}
.perm-cap{flex:0 0 190px;color:#fff;font-size:var(--fs-3)}
.perm-row .sel{width:auto;min-width:120px}
.perm-list{display:flex;flex-wrap:wrap;gap:14px}
.perm-list .flag-row{margin-bottom:0}
.perm-ex{display:flex;flex-direction:column;gap:4px;flex:1}
.perm-ex-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
@media (max-width:720px){
  .perm-row{align-items:flex-start;flex-direction:column;gap:6px}
  .perm-cap{flex:0 0 auto}
}

/* ---------- handing over work (2026-08-25) ---------- */
.ho-list{display:flex;flex-direction:column;gap:4px;max-height:240px;overflow-y:auto}
.ho-row{display:flex;align-items:center;gap:12px;padding:5px 0}
.ho-row + .ho-row{border-top:var(--stroke) solid var(--line-08)}
.ho-name{color:#fff;font-size:var(--fs-3)}
.ho-stay{margin-top:10px}

/* ---- the POF library (2026-08-26): every board, both runs, whether or not it has been done ---- */
.pof-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(230px,100%),1fr));gap:var(--sp-2);
  margin-top:var(--sp-2)}
/* THE WHOLE FACE OF A CLOSED CARD IS THE CONTROL (2026-08-31, user). The card's own padding moved
   ONTO the button, so there is no dead border of card left around it to click and miss. The open
   body keeps the padding back, because its rows carry buttons of their own. */
.pof-site{padding:0;transition:border-color var(--t-micro) var(--ease),transform var(--t-micro) var(--ease)}
/* THE CARD ANSWERS THE POINTER (2026-09-18, user: "there are no ui interactions"): a small lift
   and a brighter hairline, transform only so the grid never reflows. */
.pof-site:hover{border-color:var(--line-40);transform:translateY(-2px)}
.pof-site.needs:hover{border-color:var(--warn)}
.pof-site-top{display:block;width:100%;padding:14px;background:none;border:0;
  cursor:pointer;color:inherit;text-align:left;font:inherit}
.pof-site-head{display:flex;align-items:center;gap:10px;width:100%;
  color:inherit;text-align:left}
.pof-site-n{color:#fff;font-size:var(--fs-4)}
.pof-site .spacer{flex:1 1 auto}
.pof-runs{display:flex;gap:8px;margin-top:12px}
.pof-run{flex:1 1 0;display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:8px 10px;border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:var(--grey-45);
  transition:border-color var(--t-micro) var(--ease),color var(--t-micro) var(--ease)}
.pof-run.on{border-color:var(--ok);color:var(--ok)}
/* the run still missing while its sibling is filled carries the attention colour (2026-09-18),
   the same warn edge the card itself uses, so half-photographed says WHICH half when closed */
.pof-run.miss{border-color:rgba(232,195,107,.42);color:var(--warn)}
/* the open body ARRIVES rather than snapping in: a keyframe, never a transition, because the
   node is appended and animated in the same frame (the 2026-08-27 rule) */
.pof-body{margin:0 14px 14px;padding-top:12px;border-top:var(--stroke) solid var(--line-08);
  animation:pofReveal .45s var(--ease) both}
@keyframes pofReveal{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.pof-run-h{margin:10px 0 6px;color:#fff}
.pof-site.has{border-color:var(--line-22)}
/* A BOARD WITH PICTURES NOBODY HAS ASSIGNED (2026-09-01, user). The attention edge is the SAME one
   the waiting artwork card carries, so the two do not become two different languages for "somebody
   still has to do something here". It is declared AFTER `.has` deliberately: a board can be both,
   and what is waiting outranks what is merely filled. */
.pof-site.needs{border-color:rgba(232,195,107,.42)}
.pof-row .btn{align-self:center}
/* THE THUMB (2026-09-18): the picture itself leads the row and is a door to the viewer. */
.pof-thumb{flex:0 0 auto;width:56px;height:42px;padding:0;overflow:hidden;
  display:flex;align-items:center;justify-content:center;cursor:pointer;
  background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:var(--grey-45);
  transition:border-color var(--t-micro) var(--ease)}
.pof-thumb:hover{border-color:var(--hl)}
.pof-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.pt-glyph svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round}
/* THE WAITING LIST UNDER THE BOARDS (2026-09-29, user); the fold it replaces is gone. The board
   dialog's body keeps the `.pof-body` name so the reveal keyframe and the row rules apply, and
   drops the card margins the in-column body carried. */
.pof-empty-t{color:#fff;font-size:var(--fs-4)}
.pof-wait{margin-top:var(--sp-4)}
.pof-wait-head{display:flex;align-items:center;gap:10px;margin-bottom:6px}
.pof-site.off{opacity:.6}
.pof-modal .pof-body{margin:0;padding-top:0;border-top:0}
.pof-modal .pof-run-h{margin:14px 0 6px}
.pof-modal .pof-run-h:first-child{margin-top:0}
/* the head's warn chip became a BUTTON (2026-09-18): a button.chip resets its button skin and
   says on hover that it goes somewhere */
button.chip{cursor:pointer;font-family:inherit;transition:border-color var(--t-micro) var(--ease)}
button.chip.warn:hover{border-color:var(--warn)}
@media (prefers-reduced-motion:reduce){
  .pof-site,.pof-site:hover{transform:none}
  .pof-body{animation:none}
}

/* ===================== the CI cursor: an LED ring + a glint dot =====================
   PORTED VERBATIM from the CI pack (`brand-ci/evolv-outdoor-ci/index.html`), which is the source of
   truth for it, rather than rewritten from the description. The ring lerp-follows the pointer, grows
   and brightens over anything interactive and contracts on press.
   FINE POINTERS ONLY. On a touch screen there is no pointer to follow and hiding the real cursor
   would leave nothing at all, so the whole thing is off there and under reduced motion. */
/* THE RING AND THE DOT WENT ON 2026-09-07 (user: "i dont want an ellipse with an effect normal
   cursor shape with minimal effect but matched to ci"). A 34px ring that lerp-followed the pointer
   and grew to 58px over anything clickable, with `cursor:none!important` on every element beneath
   it, so the SVG arrow below was never actually on screen: what a person saw was the ellipse.
   Removing it is what puts the arrow back. */

/* ===================== the section rail =====================
   ONE DOT PER SUBJECT ON THE PAGE (2026-09-03, user: "a little line and ellipse with dot on section
   scrolling tool to make nav quicker"). Built from `.page-stack`'s own children, so it can never
   list a section that is not there: if a page grows a block, the rail grows a dot.
   IT HIDES ITSELF when there is nothing to jump between, and on narrow screens, where a fixed rail
   would sit on top of the content it is meant to navigate. */
.srail{position:fixed;right:calc(var(--gutter) / 2);top:50%;transform:translateY(-50%);z-index:60;
  display:flex;flex-direction:column;align-items:center;gap:0;pointer-events:auto}
.srail-line{width:var(--stroke);flex:0 0 auto;background:var(--line-08)}
.srail-dot{position:relative;display:block;width:26px;height:26px;padding:0;background:none;border:0;
  cursor:pointer;transition:all var(--t-micro) var(--ease)}
.srail-dot::before{content:"";position:absolute;left:50%;top:50%;width:7px;height:7px;
  transform:translate(-50%,-50%);border-radius:50%;
  border:var(--stroke) solid var(--line-22);background:transparent;
  transition:all var(--t-micro) var(--ease)}
.srail-dot:hover::before{border-color:var(--hl);background:var(--hl-12)}
.srail-dot.on::before{width:11px;height:11px;border-color:var(--hl);background:var(--hl)}
/* The name of the section appears on hover, on the left, so a dot is never a guess. */
.srail-dot .srail-lbl{position:absolute;right:calc(100% + 8px);top:50%;transform:translateY(-50%);
  white-space:nowrap;opacity:0;pointer-events:none;
  font-family:var(--font-display);text-transform:uppercase;font-size:var(--fs-1);letter-spacing:var(--ls-btn);
  color:#fff;background:rgba(0,0,0,.72);border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;padding:4px 9px;
  transition:opacity var(--t-micro) var(--ease)}
.srail-dot:hover .srail-lbl,.srail-dot:focus-visible .srail-lbl{opacity:1}
@media (max-width:1200px){.srail{display:none}}

/* ===================== responsive: the frame on tablet and phone ===================== */
/* 2026-09-23, user: "making the whole system responsive to different devices".
   THE FIXED CANVASES ARE DELIBERATELY OUTSIDE THIS SECTION: a presentation slide and an A4
   sheet lay out at their design size and SCALE (the 2026-08-31 rule), so no width media rule
   may touch `.pdeck-slide` or `.pp-sheet` — the `resp:` suite refuses one that does. What
   adapts is the CHROME around the work: the frame, the nav, the modals, the grids and the
   touch targets. The wide DATA surfaces (availability, the flighting schedule, the sheets)
   keep their shape inside `.st-scroll` and the finger moves the window: a money grid that
   reflows is how a figure lands under the wrong month. */

/* A GRID ITEM REFUSES TO SHRINK BELOW ITS CONTENT unless told (`min-width:auto` is the grid
   default), which is how a nowrap block head and a wide table grew the whole page 63px past a
   320px phone and put the dashboard on a sideways scroll under the gutter, found LIVE at 320
   (2026-09-23, his screenshot). The page-level grids' children may always shrink: what is
   inside them wraps, or scrolls in its own `.st-scroll`. Base rules, not media rules, because
   the overflow exists at any width where the content is wider than the column. (The intake
   board joined 2026-09-27 and went with the intake card on 2026-10-08.) */
.dash-grid>*,.sc-two>*{min-width:0}

/* --- the frame: below the width where the one-row bar FITS, the bar stacks and the nav takes a
   row of its own, scrolling sideways only when even that row is too narrow. The bar keeps its
   sticky position; `height:auto` releases the fixed desktop height.
   THE BREAKPOINT IS MEASURED, NOT CHOSEN (2026-09-29): it was 860px, and every width between
   860 and about 2160 crushed the bar (the base rule above says how). Seven sections plus seven
   controls needed 1615px of page with seven text tabs; with the Site library as a billboard
   glyph (later the same day) they need 1542px, measured in headless Chrome as Chris and as the
   viewer seat; 1565 keeps the same 24px of slack. A seat with fewer sections stacks at the same
   width, deliberately: one bar, one breakpoint. The row-two nav is CENTRED while it fits, `safe`
   so an overflowing strip starts at its first tab instead of losing it off the left edge. --- */
/* MEASURED PER SEAT, NOT A BREAKPOINT (2026-10-07, user: a rep's four tabs stacked on a laptop).
   The 1565px block below was the width SEVEN sections need, so every seat stacked there whatever
   it carried. `fitTopbar` in js/app.js measures the bar's three groups against its width after
   every render and on every resize, and puts `.stack` on the bar only when they do not fit. The
   rules are the same; only the switch moved from the viewport to the measurement. */
/* the row without its air: the page's side taper goes and the tabs close up a little, so a seat
   fits one row on a laptop before it has to stack */
.topbar.tight{padding-left:var(--gutter);padding-right:var(--gutter);gap:10px}
.topbar.tight .tb-side{gap:8px}
.topbar.tight .nav-tab{padding:8px 6px}
.topbar.stack{grid-template-columns:auto 1fr;grid-template-rows:auto auto;height:auto;
  padding-top:10px;padding-bottom:6px;row-gap:2px}
.topbar.stack .tb-side{grid-row:1;grid-column:1}
.topbar.stack .tb-side.right{grid-column:2}
.topbar.stack .nav{grid-row:2;grid-column:1 / -1;justify-content:flex-start;justify-content:safe center;
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
  /* the strip says it continues: the right edge fades rather than cutting a word dead */
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent);
  mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent)}
.topbar.stack .nav::-webkit-scrollbar{display:none}
.topbar.stack .nav-tab{white-space:nowrap;flex:0 0 auto}
/* the proposal builder's chrome goes single-column early: the rail beside an A4 sheet
   needs more room than a tablet has. The SHEET itself is untouched and keeps its fit scale. */
@media (max-width:1150px){
  .pp-body{flex-direction:column}
  .pp-side{flex:1 1 auto;width:100%}
}

/* --- the phone band: the page breathes, the modals take the screen --- */
@media (max-width:600px){
  /* the 100px taper is desktop air; on a phone the gutter alone is the padding. The block
     heading steps down a cut with it: at 1.65rem the single word AVAILABILITY is wider than
     a 320px screen minus its icon, and a word cannot wrap, so the type scales instead. */
  :root{--pad-x:var(--gutter);--fs-greeting:clamp(1.7rem,9vw,2.2rem);--fs-8:1.35rem}
  /* THE BAR'S CONTROLS NEVER CRUSH (2026-09-23, his 320px screenshot: two buttons squeezed
     to slivers and Sign out wrapped to two lines). Flex was letting every control shrink to
     make the row "fit"; nothing here may give way, so the row is instead made to genuinely
     fit: the full-screen toggle goes (a phone browser owns that gesture), the gaps and the
     mark come down, and the sign-out stays one line at a smaller cut. */
  .tb-side>*{flex:0 0 auto}
  .topbar{gap:8px}
  .tb-side{gap:6px}
  .topbar .evos .evos-type{height:13px}
  .topbar .fs-btn{display:none}
  .iconbtn{width:32px;height:32px}
  /* the arithmetic has to close: bell 32 + avatar 32 + this button inside the right column,
     or flex-end pushes the overflow LEFT and the bell lands on the mark (his screenshot) */
  .tb-side .btn.sm{padding:7px 8px;font-size:var(--fs-1);letter-spacing:.04em;white-space:nowrap}
  .nav-tab{padding:8px 10px}
  /* the block heads may wrap their counts under the title instead of widening the card */
  .block-toggle{flex-wrap:wrap;row-gap:2px}
  /* the greeting keeps its lead without the desktop's air above and below it */
  .dash-head{margin-top:10px;margin-bottom:24px;padding-top:14px;padding-bottom:10px}
  /* the login's seat grid loses its height cap: capped, the rows compressed below their own
     content and a three-line title spilled under the next card (his 320px screenshot). A
     phone scrolls the page instead. */
  .who-grid{max-height:none;overflow-y:visible;padding-right:0}
  /* the page rhythm steps down with the type: 72px between subjects reads as a void on a
     phone. NARROWS the one-rhythm rule rather than reversing it: still one value, one step
     smaller, on every page alike. */
  .page-stack > * + *{margin-top:var(--sp-6)}
  .dash-grid{gap:var(--sp-6)}
  .overlay{padding:10px}
  .modal{padding:20px 16px}
  .modal-foot{flex-wrap:wrap}
  /* 16px is the size below which iPhones zoom the page on focus, which reads as the layout
     jumping; the fixed canvases carry no inputs, so this reaches only the working chrome.
     THE BARE SELECTORS LOST (found 2026-09-29): every styled field is sized by a CLASS rule, and
     `.field input` outranks `input`, so the floor reached almost nothing and an iPhone still
     zoomed in most forms. Each field rule that sets a size under 16px is restated here at its own
     specificity, later in the file, so it wins; `resp:` fails if a new one is added without it. */
  input,select,textarea,.field input,.lib-f input,.sel,input[type=date],.cat-row input.cat-name,.act-search,
  .gb-input,.ll-tools .sel,.prop-gal-i input,.prop-opex-row input{font-size:16px}
  .alloc-row{grid-template-columns:1fr}
  .alloc-board{padding-top:0}
}
@media (max-width:520px){.qgrid{grid-template-columns:1fr}}

/* --- touch: a finger needs a target, whatever the screen width --- */
@media (pointer:coarse){
  .btn,.tab,.nav-tab,.wz-dot{min-height:40px}
  .nav-tab.nav-icon{min-width:44px}
  /* the bar's three icon buttons sat at 32px on touch (the phone band's own bar-crush cut),
     under this block's own rule — found by the assistant's device round (2026-09-27). Grown on
     BOTH axes, because a 32-wide 40-tall target is half a target; measured live at 320 first:
     the right group closes at 298 of 320 with the mark clear, so the crush does not return. */
  .iconbtn{min-width:40px;min-height:40px}
  .modal .x{padding:8px;margin:-8px}
  .pill-clear{min-height:36px;padding:8px 14px}
}

/* ---------- the site library (2026-09-28) ---------- */
/* The card is the register's board made visible: cover leading, name in the display face,
   the count line saying how complete the record is. The whole face is the control. */
.lib-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(230px,100%),1fr));gap:var(--sp-2);margin-top:var(--sp-2)}
.lib-card{padding:0;overflow:hidden}
.lib-card.off .lib-face{opacity:.55}
.lib-acts{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.lib-reg-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap}
.lib-face{display:flex;flex-direction:column;align-items:stretch;gap:5px;width:100%;padding:13px;
  background:none;border:none;cursor:pointer;text-align:left;color:var(--grey-70);
  transition:background var(--t-micro) var(--ease)}
.lib-face:hover{background:rgba(255,255,255,.03)}
.lib-cover{display:flex;align-items:center;justify-content:center;width:100%;aspect-ratio:16/9;
  overflow:hidden;background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:var(--grey-45);margin-bottom:4px}
.lib-cover img{width:100%;height:100%;object-fit:cover;display:block}
.lib-cover .pt-glyph svg{width:26px;height:26px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round}
.lib-name{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.05em;
  color:#fff;font-size:var(--fs-4)}
.lib-sub,.lib-meta{display:block}
/* the record modal: gallery strip first, then the answers in their groups */
.lib-body .lib-gallery{margin-bottom:var(--sp-2)}
.lib-thumbs{display:flex;flex-wrap:wrap;gap:12px;align-items:flex-start}
.lib-cell{display:flex;flex-direction:column;gap:4px}
.lib-thumb{width:96px;height:72px}
.lib-thumb .pt-glyph svg{width:26px;height:26px}
.lib-cell-acts{display:flex;gap:10px;align-items:center;min-height:16px}
.lib-add-lbl{font-size:var(--fs-2);text-transform:uppercase;letter-spacing:.06em}
.lib-step-h{font-size:var(--fs-4);margin-top:var(--sp-3);margin-bottom:10px}
.lib-fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(240px,100%),1fr));
  gap:12px 18px;align-items:start}
.lib-f{display:flex;flex-direction:column;gap:3px;min-width:0}
.lib-f.wide{grid-column:1/-1}
.lib-f-v{color:#fff;overflow-wrap:break-word}
.lib-f input,.lib-f select,.lib-f textarea{width:100%;margin-top:4px}   /* the label-to-control rhythm .field keeps at 7px */
/* the field manager: one row per field, its scope beside it, the action at the end */
.lib-mgr{display:flex;flex-direction:column}
.lib-mgr-row{display:flex;align-items:center;gap:10px;padding:8px 0}
.lib-mgr-row + .lib-mgr-row{border-top:var(--stroke) solid var(--line-08)}
.lib-addf{display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:end}
@media (max-width:700px){.lib-addf{grid-template-columns:1fr}}

/* the development clocks: the admin figures' own tiles, an input where the MD's value sits */
.sdclock-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));gap:var(--sp-2);margin-top:var(--sp-1);max-width:780px}
.sdclock-tile .cap{margin-top:8px}
.sdclock-val{display:flex;align-items:baseline;gap:10px;margin-top:6px}
.sdclock-val input{width:104px;background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;color:#fff;font-family:var(--font-display);
  font-size:var(--fs-7);line-height:1;padding:8px 12px;
  transition:border-color var(--t-micro) var(--ease)}
.sdclock-val input:focus{outline:none;border-color:var(--hl)}
.sdclock-val input::-webkit-outer-spin-button,.sdclock-val input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.sdclock-val input[type=number]{appearance:textfield;-moz-appearance:textfield}
.sdclock-unit{color:var(--grey-70);text-transform:uppercase;font-size:var(--fs-2);letter-spacing:.06em}
.sdclock-act{margin-top:var(--sp-2)}

/* the clocks table: the row is the control, and it says so on hover */
.sd-clock-table .sdct-row{cursor:pointer;transition:background var(--t-micro) var(--ease)}
.sd-clock-table .sdct-row:hover{background:rgba(255,255,255,.04)}
.sd-clock-table .sdct-name{color:#fff;font-family:var(--font-display);text-transform:uppercase;letter-spacing:.04em}

/* ---------- the three pocket tools (2026-09-28) ---------- */
.tool-glyph svg{width:19px;height:19px;display:block}
.tool-modal{max-width:640px}
/* the history search: one box, rows that say why they matched */
.hs-body{min-height:220px}
.hs-count{margin:2px 0 8px}
.hs-row{display:flex;flex-direction:column;gap:3px;width:100%;text-align:left;padding:10px 12px;
  background:none;border:none;border-top:var(--stroke) solid var(--line-08);cursor:pointer;
  font:inherit;color:inherit;transition:background var(--t-micro) var(--ease)}
.hs-row:hover{background:rgba(255,255,255,.04)}
.hs-row.hs-still,.hs-row.hs-still:hover{cursor:default;background:none}
.hs-main{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.hs-name{color:#fff}
.hs-why{color:var(--grey-45)}
/* the calculator: a display and seventeen keys */
.calc-modal{max-width:280px}
.calc-body{outline:none}
.calc-display{font-family:var(--font-display);font-size:var(--fs-7);color:#fff;text-align:right;
  padding:10px 12px;margin-bottom:10px;background:rgba(255,255,255,.02);
  border:var(--stroke) solid var(--line-14);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  overflow:hidden;white-space:nowrap}
.calc-pad{display:grid;grid-template-columns:repeat(4,1fr);gap:7px}
.calc-key{padding:11px 0;font-family:var(--font-display);font-size:var(--fs-4);color:#fff;cursor:pointer;
  background:rgba(255,255,255,.03);border:var(--stroke) solid var(--line-08);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  transition:background var(--t-micro) var(--ease),border-color var(--t-micro) var(--ease)}
.calc-key:hover{background:rgba(255,255,255,.07);border-color:var(--line-40)}
.calc-key.op{color:var(--grey-70)}
.calc-key.eq{grid-row:span 3;background:rgba(18,40,76,.55);border-color:var(--line-14)}
.calc-key.eq:hover{border-color:var(--hl)}
/* the to do list: add, done, delete, and the completed roll below */
/* the composer: one cut-frame row holding the +, the field and Add; it lights on focus the way
   every E.V.O.S. field does (white hairline, a touch more fill), and the field itself draws no
   box of its own, so the browser's white default can never show through again */
.todo-add{display:flex;align-items:center;gap:10px;margin-bottom:var(--sp-3);padding:5px 5px 5px 14px;
  background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);
  border-radius:var(--notch-sm) 0 var(--notch-sm) 0;
  transition:border-color var(--t-micro) var(--ease),background var(--t-micro) var(--ease)}
.todo-add:hover{border-color:var(--line-22)}
.todo-add:focus-within{border-color:var(--hl);background:rgba(255,255,255,.04)}
.todo-plus{flex:0 0 auto;color:var(--grey-45);font-size:var(--fs-5);line-height:1;
  transition:color var(--t-micro) var(--ease)}
.todo-add:focus-within .todo-plus{color:#fff}
.todo-input{flex:1 1 auto;min-width:0;padding:9px 0;background:none;border:0;outline:none;
  color:#fff;font-family:var(--font-body);font-size:var(--fs-5)}
.todo-input::placeholder{color:var(--grey-45)}
.todo-add .btn{flex:0 0 auto}
.todo-row{display:flex;align-items:center;gap:12px;padding:10px 2px;
  border-top:var(--stroke) solid var(--line-08)}
.todo-row .cap{flex:0 0 auto;white-space:nowrap}
.todo-row .linkbtn{flex:0 0 auto;padding:4px 2px}
/* the phone band's 16px input rule is a bare `input`, which this class outranks: restated here
   so an iPhone does not zoom the page when the composer takes focus */
@media (max-width:600px){.todo-input{font-size:16px}}
.todo-text{flex:1;overflow-wrap:anywhere;color:#fff}
.todo-row.done .todo-text{color:var(--grey-45);text-decoration:line-through}
.todo-done-h{font-size:var(--fs-4);margin-top:var(--sp-2);margin-bottom:2px}
/* the bar holds seven controls now: on a phone the right group may wrap instead of crushing
   the mark (the 2026-09-23 bar rule: the mark stays clear) */
@media (max-width:600px){.tb-side.right{flex-wrap:wrap;justify-content:flex-end;row-gap:4px}}

/* ---------- the POF library rows, reworked (2026-09-28, his screenshot) ---------- */
/* Scoped to the library card's own body: `.pof-row` elsewhere (tickets, the dev bucket, the
   deal's proof list) keeps its simple flex. Two lines, one hierarchy: picture beside its words,
   the claim state as a chip, every action a real button in one row. */
.chip.ok{background:rgba(91,224,176,.12);color:var(--ok);border-color:transparent}
.pof-sec-head{display:flex;align-items:center;gap:10px;margin-bottom:6px}
.pof-sec-head h3{margin:0}
/* `.pof-rows` is the same row list outside the library card (the campaign's own proof section,
   2026-09-29): one set of rules, two scopes, so a picture reads the same wherever it is listed */
.pof-rows{margin:4px 0 6px}
.pof-body .pof-row,.pof-rows .pof-row{display:flex;flex-direction:column;align-items:stretch;gap:8px;
  padding:12px 0;border-top:var(--stroke) solid var(--line-08)}
.pof-row-main{display:flex;gap:12px;align-items:flex-start;min-width:0}
.pof-body .pof-thumb,.pof-rows .pof-thumb{width:96px;height:72px}
.pof-body .pof-thumb .pt-glyph svg,.pof-rows .pof-thumb .pt-glyph svg{width:26px;height:26px}
.pof-info{display:flex;flex-direction:column;gap:5px;min-width:0}
.pof-body .pof-name,.pof-rows .pof-name{display:flex;flex-direction:column;gap:2px}
.pof-title{color:#fff;font-size:var(--fs-4)}
.pof-state{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.pof-acts{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.pof-acts .btn{flex:0 0 auto}
.pof-acts .pof-del .lbl{color:var(--warn)}
/* the board head: the name never wraps mid-word into the counts */
.pof-site-n{white-space:nowrap}
.pof-site-head{flex-wrap:wrap;row-gap:4px}
/* POF received: one row per campaign, the whole row the door, the verdict chip leading */
.pofin{display:flex;flex-direction:column;gap:10px;margin-top:var(--sp-1)}
.pofin-row{display:flex;flex-direction:column;align-items:stretch;gap:5px;width:100%;
  text-align:left;padding:13px 15px;font:inherit;color:var(--grey-70);cursor:pointer;
  background:none;border:none;transition:background var(--t-micro) var(--ease)}
.pofin-row:hover{background:rgba(255,255,255,.04)}
.pofin-main{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.pofin-name{color:#fff;font-size:var(--fs-4)}

/* ---------- the investor's dashboard (2026-09-29, rebuilt the same day as a story) ----------
   THE OUTSIDE SEAT'S ONE PAGE: a headline band, then four chapters in the page rhythm, each with a
   rule that line-draws as it arrives. A step larger everywhere (the --fs-inv-* tokens), one column
   on a phone, the marks HTML so the words stay crisp, the boards the register's own glyph. White and
   grey tints carry magnitude; the semantic colours carry state only. No `.cap` under a heading here
   (the nav rule): the small lines are `.inv-lead` and `.inv-note`. */
.inv{font-size:var(--fs-inv-body)}
.inv-asof{color:var(--grey-45);letter-spacing:.08em;text-transform:uppercase;font-size:var(--fs-inv-lab)}
/* the band */
.inv-band{padding:var(--sp-5) var(--sp-5) var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-4);text-align:center;align-items:center}
.inv-band-figs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-4);width:100%}
.inv-tile{min-width:0;padding:0 var(--sp-2)}
.inv-tile-l{font-size:var(--fs-inv-lab);letter-spacing:.1em;text-transform:uppercase;color:var(--grey-45);margin-bottom:10px}
.inv-tile-v{font-family:var(--font-display);font-size:var(--fs-inv-hero);color:#fff;line-height:1;letter-spacing:.01em;overflow-wrap:anywhere}
.inv-tile-s{color:var(--grey-70);margin-top:10px}
.inv-track{width:100%;max-width:820px;display:flex;flex-direction:column;gap:8px}
.inv-track-line{position:relative;height:3px;background:var(--grey-22);border-radius:2px}
.inv-track-fill{position:absolute;left:0;top:0;bottom:0;background:var(--hl);border-radius:2px;transition:width 1s var(--ease)}
.inv-track-mark{position:absolute;top:50%;width:11px;height:11px;margin:-5.5px 0 0 -5.5px;border-radius:50%;border:2px solid var(--hl);background:#000;box-sizing:border-box}
.inv-track-txt{display:flex;justify-content:space-between;gap:var(--sp-3);color:var(--grey-70);font-size:var(--fs-inv-lab);letter-spacing:.06em;text-transform:uppercase}
/* cards within cards (his fourth word): the chapter is the lit surface, the groups inside it sit
   on quieter cards. The light still goes on the navy, never straight on the dark (2026-08-19),
   at a lower lift than the chapter. The inner card's own hover halftone stays. */
.inv-in{padding:var(--sp-3);background:linear-gradient(180deg,rgba(224,224,223,.03),transparent 46%),
  linear-gradient(180deg,rgba(18,40,76,.24),rgba(18,40,76,.12))}
.inv-in-chart{padding-top:var(--sp-4)}
.inv-audience{margin-top:0}
.inv-band .inv-in.inv-tile{padding:var(--sp-4) var(--sp-3)}
/* the chapters: lit cards in a grid that stacks (his third word, the combo of the two cuts) */
.inv-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-4);align-items:start}
.inv-ch{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0;padding:var(--sp-4)}
.inv-ch.wide{grid-column:1/-1}
.inv-ch-head{display:flex;flex-direction:column;gap:6px}
.inv-ch-head h2{margin:0}
.inv-lead{color:var(--grey-70);line-height:1.45;max-width:64ch}
.inv-note{color:var(--grey-70);line-height:1.45}
.inv-empty{color:var(--grey-45);padding:var(--sp-3) 0}
.inv-figs{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(170px,100%),1fr));gap:var(--sp-4) var(--sp-3)}
.inv-fig{min-width:0}
.inv-fig-l{font-size:var(--fs-inv-lab);letter-spacing:.08em;text-transform:uppercase;color:var(--grey-45);margin-bottom:6px}
.inv-fig-v{font-family:var(--font-display);font-size:var(--fs-inv-fig);color:#fff;line-height:1.05;overflow-wrap:anywhere}
.inv-fig-v.ok{color:var(--ok)}
/* bars on a baseline */
.inv-chart{display:flex;flex-direction:column;gap:8px;min-width:0}
.inv-plot{display:grid;gap:4px;height:220px;position:relative;border-bottom:1px solid var(--line-14);padding-top:1.6em;box-sizing:border-box}
.inv-col{display:flex;flex-direction:column;justify-content:flex-end;min-width:0;height:100%}
.inv-bar{position:relative;width:100%;border-radius:4px 4px 0 0;background:var(--grey-45);transition:height .7s var(--ease)}
.inv-bar.ahead{background:none;border:1px solid var(--grey-45);border-bottom:0;box-sizing:border-box}
.inv-bar.lit{background:var(--hl)}
.inv-val{position:absolute;left:50%;bottom:100%;transform:translateX(-50%);margin-bottom:5px;font-size:var(--fs-2);color:var(--grey-70);white-space:nowrap}
.inv-rule-target{position:absolute;left:0;right:0;height:0;border-top:1px dashed var(--grey-45);pointer-events:none}
.inv-rule-lab{position:absolute;right:0;bottom:3px;font-size:var(--fs-1);letter-spacing:.06em;text-transform:uppercase;color:var(--grey-45);background:#000;padding:0 4px}
.inv-labels{display:grid;gap:4px}
.inv-lab{font-size:var(--fs-inv-lab);color:var(--grey-70);text-align:center;white-space:nowrap;overflow:hidden}
.inv-chart.tight .inv-lab{font-size:var(--fs-2)}
.inv-lab-s{display:none}
.inv-key{display:flex;gap:16px;flex-wrap:wrap;color:var(--grey-70);font-size:var(--fs-inv-lab)}
.inv-k{display:inline-flex;align-items:center;gap:7px}
.inv-k i{width:12px;height:12px;border-radius:3px;display:inline-block;background:var(--grey-45)}
.inv-k.a i{background:var(--grey-45)}
.inv-k.b i{background:var(--grey-70)}
.inv-k.c i{background:var(--grey-22)}
.inv-k.lit i{background:var(--hl)}
.inv-k.ahead i{background:none;border:1px solid var(--grey-45);box-sizing:border-box}
/* the boards as glyphs */
.inv-glyphs{display:flex;flex-wrap:wrap;gap:8px}
.inv-glyph{display:inline-flex;width:34px;height:34px;color:var(--grey-45);opacity:.55;transition:opacity .5s var(--ease)}
.inv-glyph svg{width:100%;height:100%;display:block;fill:none;stroke:currentColor;stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
.inv-glyph.lit{color:var(--hl);opacity:1;filter:drop-shadow(0 0 6px rgba(255,255,255,.35))}
.inv-glyph.lit rect{fill:rgba(255,255,255,.12)}
.inv-glyph.static{color:var(--grey-70);opacity:.9}
.inv-sell{display:grid;grid-template-columns:1fr;gap:var(--sp-4);align-items:start}
.inv-sell-boards{display:flex;flex-direction:column;gap:12px;min-width:0}
/* the weekly meters */
.inv-meters{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));gap:var(--sp-3)}
.inv-meter{display:flex;flex-direction:column;gap:8px;min-width:0}
.inv-meter-l{display:flex;justify-content:space-between;gap:8px;font-size:var(--fs-inv-lab);letter-spacing:.06em;text-transform:uppercase;color:var(--grey-45);white-space:nowrap}
.inv-meter-p{color:#fff;font-family:var(--font-display)}
.inv-meter.lit .inv-meter-l{color:var(--grey-70)}
.inv-meter-line{height:6px;background:var(--grey-22);border-radius:3px;overflow:hidden}
.inv-meter-fill{display:block;height:100%;background:var(--grey-70);border-radius:3px;transition:width .8s var(--ease)}
.inv-meter.lit .inv-meter-fill{background:var(--hl)}
.inv-meter-s{font-size:var(--fs-2);color:var(--grey-45)}
/* the forecast and the funnel */
.inv-fc{display:grid;grid-template-columns:1fr;gap:var(--sp-4);align-items:start}
.inv-fc-left,.inv-fc-right{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0}
.inv-funnel{display:flex;flex-direction:column;gap:12px}
.inv-fn-row{display:grid;grid-template-columns:minmax(0,1fr);gap:4px}
.inv-fn-l{font-size:var(--fs-inv-lab);letter-spacing:.08em;text-transform:uppercase;color:var(--grey-45)}
.inv-fn-band{height:34px;border-radius:0 6px 6px 0;background:linear-gradient(90deg,var(--grey-45),var(--grey-22));display:flex;align-items:center;padding:0 12px;box-sizing:border-box;min-width:3em;transition:width .8s var(--ease)}
.inv-fn-band.ok{background:linear-gradient(90deg,var(--ok),rgba(91,224,176,.35))}
.inv-fn-band.none{background:none;border:1px solid var(--grey-22)}
.inv-fn-n{font-family:var(--font-display);color:#fff;font-size:var(--fs-6)}
.inv-fn-band.none .inv-fn-n{color:var(--grey-45)}
.inv-fn-v{color:var(--grey-70)}
/* the network and the audience */
.inv-net{display:flex;flex-direction:column;gap:var(--sp-3)}
.inv-sell{gap:var(--sp-3)}
.inv-fc{gap:var(--sp-3)}
.inv-net-row{display:flex;flex-direction:column;gap:10px}
.inv-audience{display:flex;flex-direction:column;gap:var(--sp-3);margin-top:var(--sp-2)}
.inv-audience h2{margin:0}
.inv-split{display:flex;height:6px;border-radius:3px;overflow:hidden;background:var(--grey-22);gap:2px}
.inv-seg{display:block;height:100%}
.inv-seg.a{background:var(--hl)}
.inv-seg.b{background:var(--grey-70)}
.inv-seg.c{background:var(--grey-45)}
/* arrival: a chapter fades up as it scrolls in, and the rule draws */
.inv-ch,.inv-band{opacity:0;transform:translateY(14px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.inv-ch.in,.inv-band.in{opacity:1;transform:none}
@media (max-width:900px){.inv-grid{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){
  .inv-ch,.inv-band{opacity:1;transform:none;transition:none}
  .inv-bar,.inv-meter-fill,.inv-fn-band,.inv-track-fill{transition:none}
}
@media (max-width:640px){
  .inv-band{padding:var(--sp-4) var(--sp-3)}
  .inv-band-figs{grid-template-columns:1fr;gap:var(--sp-4)}
  .inv-plot{height:170px}
  .inv-chart.tight .inv-lab-l{display:none}
  .inv-chart.tight .inv-lab-s{display:inline}
  .inv-fig-v{font-size:var(--fs-inv-fig-phone)}
  .inv-figs{grid-template-columns:repeat(2,minmax(0,1fr))}
  .inv-sell,.inv-fc{grid-template-columns:1fr}
  .inv-glyph{width:28px;height:28px}
  .inv-meters{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* ---------- what is waiting for the backend (2026-09-30) ---------- */
.ask-block .ask-row{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-3) 0}
.ask-block .ask-row + .ask-row{border-top:var(--stroke) solid var(--line-14)}
.ask-block .ask-row.open .ask-line{color:var(--hl)}
.ask-block .ask-line{font-size:var(--fs-3);overflow-wrap:anywhere}
.ask-block .ask-row .btn{align-self:flex-start;margin-top:var(--sp-1)}

/* ---------- a face beside every action (2026-09-30) ----------
 * The small round photo `h` puts in front of a by-line. The initials of a seat with no photo are
 * drawn from `data-i`, so they are never part of the words. A span keeps its place in a line; a
 * block lines its face up with its first line. */
.avatar.xs{width:var(--face);height:var(--face);flex:0 0 auto;font-size:var(--fs-face);letter-spacing:0}
.avatar.xs[data-i]::before{content:attr(data-i)}
.faced{display:inline-flex;align-items:center;gap:var(--sp-1);max-width:100%;min-width:0}
div.faced{display:flex;align-items:flex-start}
div.faced > .avatar.xs{margin-top:1px}
.log-say{min-width:0;overflow-wrap:anywhere}

/* ---------- the profile page and the team directory beside it (2026-09-30) ---------- */
.profile-grid{display:grid;grid-template-columns:minmax(0,560px) minmax(0,1fr);gap:var(--sp-5);align-items:start}
.profile-grid > *{min-width:0}
.dir{padding:var(--sp-4);container-type:inline-size}
.dir .dir-row{display:grid;grid-template-columns:auto minmax(0,1fr) minmax(0,1.2fr);gap:var(--sp-3);align-items:center;padding:var(--sp-2) 0}
.dir .dir-row + .dir-row{border-top:var(--stroke) solid var(--line-14)}
.dir .dir-name{color:#fff;font-size:var(--fs-4);font-weight:600;overflow-wrap:anywhere}
.dir .dir-reach{display:flex;flex-direction:column;gap:2px;min-width:0;text-align:right}
.dir .dir-top{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;min-width:0}
.dir .dir-seen{text-transform:none;letter-spacing:0;white-space:nowrap}
.dir .dir-seen:hover,.dir .dir-seen:focus-visible{border-color:var(--hl);color:#fff;outline:none}
.dir .dir-seen.now{background:var(--hl-12);color:var(--hl);border-color:transparent}
.sh-body{min-height:220px}
.sh-day{color:#fff;font-size:var(--fs-3);font-weight:600;margin:var(--sp-3) 0 var(--sp-1)}
.sh-day:first-child{margin-top:0}
.sh-row{display:grid;grid-template-columns:3.2em minmax(0,1fr) auto;gap:var(--sp-2);align-items:baseline;padding:var(--sp-2) 0}
.sh-row + .sh-row{border-top:var(--stroke) solid var(--line-08)}
.sh-time{color:var(--grey-45);font-size:var(--fs-2);font-variant-numeric:tabular-nums}
.sh-text{color:var(--grey-70);font-size:var(--fs-3);overflow-wrap:anywhere}
.sh-row.signin .sh-text{color:var(--grey-45)}
.dir .dir-link{color:var(--hl);font-size:var(--fs-3);text-decoration:none;overflow-wrap:anywhere}
.dir .dir-link:hover{text-decoration:underline}
@media (max-width:1100px){
  .profile-grid{grid-template-columns:minmax(0,1fr)}
}
/* the row answers to the width of the DIRECTORY, not of the window: beside the profile it is
 * narrow on a laptop and wide on a desk screen, and underneath it is as wide as the page */
@container (max-width:460px){
  .dir .dir-row{grid-template-columns:auto minmax(0,1fr)}
  .dir .dir-reach{grid-column:2;text-align:left}
}

/* ---------- a person's photo, large (2026-09-30) ---------- */
.dir .dir-face{background:none;border:none;padding:0;cursor:pointer;border-radius:50%;line-height:0;
  transition:transform .18s var(--ease),box-shadow .18s var(--ease)}
.dir .dir-face:hover,.dir .dir-face:focus-visible{transform:scale(1.08);box-shadow:0 0 0 2px var(--hl);outline:none}
.modal.face-modal{width:min(440px,92vw)}
.face-big{display:flex;justify-content:center;padding:var(--sp-4) 0 var(--sp-3)}
.face-big img{width:min(320px,70vw);aspect-ratio:1;object-fit:cover;border-radius:50%;
  border:var(--stroke) solid var(--line-14)}
@media (prefers-reduced-motion:reduce){.dir .dir-face{transition:none}}

/* THE POF BOARD'S TICK BAR (2026-10-05): tick pictures on a board's month and assign the set at once.
   The tick is the build's own (`.tickline input`): same size, same highlight. */
.pof-pick-bar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:8px 0 10px;border-bottom:1px solid var(--line-08);margin-bottom:8px}
.pof-pick-bar .tickline{margin:0}
.pof-pick{flex:0 0 auto;width:16px;height:16px;margin:0 4px 0 0;align-self:center;accent-color:var(--hl);cursor:pointer}
.pof-pick-bar .btn[disabled]{opacity:.45;cursor:not-allowed}

/* invoicing on a Won deal (2026-10-05): a row per invoice, its three ticks beside it */
.inv-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2) var(--sp-4);padding:var(--sp-2) 0}
.inv-row + .inv-row{border-top:1px solid var(--line-08)}
.inv-main{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 180px}
.inv-n{font-size:var(--fs-4);color:var(--white)}
.inv-ticks{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4);align-items:center}
.inv-new{display:flex;flex-direction:column;gap:var(--sp-3);margin-top:var(--sp-3);padding-top:var(--sp-3);border-top:1px solid var(--line-08)}
.inv-new .field{max-width:320px}
.inv-new .btn{align-self:flex-start}

/* the adopt levers under the books section on a deal (2026-10-05) */
.books-twin .row-acts{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-3);align-items:center;margin-top:var(--sp-3)}

/* a sheet or grid row that is a deal opens it, for Finance and the directors (2026-10-05) */
tr.row-opens{cursor:pointer}
tr.row-opens:hover td,tr.row-opens:focus-visible td{background:var(--line-08)}
tr.row-opens:focus-visible{outline:1px solid var(--hl);outline-offset:-1px}

/* a row whose picture never reached the server (2026-10-05) */
.chip.bad{background:rgba(232,124,124,.14);color:var(--bad);border-color:transparent}
.pof-gone{margin-left:var(--sp-2)}

/* invoicing from the attention list (2026-10-05) */
.att-invoice{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4);align-items:center;margin-top:var(--sp-2)}
.gate-modal .inv-ticks{margin:var(--sp-3) 0}

/* ===================== 2026-11-02: who a client belongs to, the deals of the window, the bell in sections ===================== */
/* the register of clients above the book of contacts (Director → Client book, and Gavin's copy on the pipeline) */
.cb-lede{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin:18px 0 10px}
.cb-title{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.08em;font-size:var(--fs-3);color:var(--grey-70);margin:0}
.cr-list{display:flex;flex-direction:column;gap:var(--sp-3);margin-bottom:26px}
.cr-item{padding:0;overflow:visible}
.cr-head{display:flex;align-items:center;gap:16px;padding:14px 16px;cursor:pointer;flex-wrap:wrap}
.cr-item.open .cr-head{border-bottom:var(--stroke) solid var(--line-08)}
.cr-body{padding:16px}
.cr-head .cb-name{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cr-direct{font-size:var(--fs-1)}
.cr-item.cr-off{border-color:var(--line-22)}
.cr-owner{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:14px}
.cr-owner-name{color:#fff;font-size:var(--fs-5);font-weight:600}
.cr-deal-off .cbd-name{color:var(--grey-70)}
.cr-rename{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap;margin:14px 0 6px}
.cr-rename .field{flex:1 1 220px;margin:0}
.cr-rename .hint{flex-basis:100%}
.cr-move .sel{max-width:230px;padding:6px 10px}
/* the deals of the week, the month and the year */
.ds-head{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:10px}
.ds-tabs{margin:0}
.ds-lede{margin:0 0 0 2px}
.ds-card{margin-bottom:var(--sp-3)}
.ds-rows{display:grid;grid-template-columns:minmax(140px,1.4fr) auto auto;column-gap:14px;row-gap:2px;align-items:center}
.ds-row{display:grid;grid-column:1/-1;grid-template-columns:subgrid;align-items:center;padding:7px 6px;border-bottom:var(--stroke) solid var(--line-08);border-radius:var(--notch-sm) 0 var(--notch-sm) 0}
.ds-name{color:#fff;font-size:var(--fs-4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ds-val{color:#fff;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.ds-when{white-space:nowrap}
.inv .ds-block{margin-top:var(--sp-5)}
@media (max-width:720px){
  .ds-rows,.ds-row{grid-template-columns:1fr auto auto}
}
/* the bell: a count, All / Unread, rooms and days */
.ntc-head-count{font-size:var(--fs-2);color:var(--grey-45);border:var(--stroke) solid var(--line-14);border-radius:999px;padding:3px 9px;white-space:nowrap}
.ntc-head-count.hot{color:#fff;border-color:var(--line-40)}
.ntc-modal .modal-head .x{margin-left:0}
.ntc-tabs{margin:0 0 6px}
.ntc-sec h3{display:flex;align-items:center;gap:8px}
.ntc-sec h3 .count{color:var(--grey-45);letter-spacing:0;text-transform:none}
.ntc-group{margin-top:10px;padding:4px 6px 2px;border:var(--stroke) solid var(--line-08);border-radius:var(--notch-sm) 0 var(--notch-sm) 0;background:rgba(255,255,255,.012)}
.ntc-group-h{display:flex;align-items:center;gap:8px;padding:4px 4px 6px;font-size:var(--fs-2);text-transform:uppercase;letter-spacing:.08em;color:var(--grey-70)}
.ntc-group-h .count{color:var(--grey-45);text-transform:none;letter-spacing:0}
.ntc-group-h .count.hot{color:#fff}
.ntc-day{margin:12px 0 2px 2px;font-size:var(--fs-2);text-transform:uppercase;letter-spacing:.08em;color:var(--grey-45)}
.ntc-meta{display:flex;flex-wrap:wrap;gap:2px 0}
.ntc-meta span+span::before{content:'\00b7';margin:0 7px;color:var(--grey-45)}
.ntc-more{display:flex;justify-content:center;margin-top:10px}
.cr-details{margin:14px 0 4px}
.cr-details .two-col{margin-bottom:8px}
.cr-details .cb-acts{margin-top:8px}
.ntc-lede{margin:2px 0 8px 2px}
.ntc-actions .btn.on{border-color:var(--line-40);color:#fff}
/* the clocks by region and by site (2026-11-02) */
.clk .card.clk-region{margin-top:var(--sp-3);padding:14px 16px}
.clk-region-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:8px}
.clk-region-name{color:#fff;font-weight:600;font-size:var(--fs-5)}
.clk-pair{display:inline-flex;align-items:center;gap:6px}
.clk-pair input{width:70px;background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);color:#fff;padding:6px 8px;border-radius:6px;font:inherit}
.clk-pair input:focus{outline:none;border-color:var(--hl)}
.clk-own{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}
.clk-site{display:grid;grid-template-columns:minmax(140px,1fr) auto minmax(220px,1.6fr) auto;gap:10px 14px;align-items:center;padding:9px 0;border-top:var(--stroke) solid var(--line-08)}
.clk-site-id{display:flex;flex-direction:column;min-width:0}
.clk-site-name{color:#fff;font-size:var(--fs-4)}
.clk-site-date{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}
.clk-site-date input[type=date]{background:rgba(255,255,255,.02);border:var(--stroke) solid var(--line-14);color:#fff;padding:6px 8px;border-radius:6px;font:inherit;color-scheme:dark}
.clk-site-clock{display:flex;flex-direction:column;gap:6px;min-width:0}
.clk-site.sd-expired .clk-site-name{color:var(--warn)}
@media (max-width:820px){.clk-site{grid-template-columns:1fr auto}.clk-site-clock{grid-column:1/-1}.clk-site-date{grid-column:1/-1}}
