/* PULSE 20.14.151 — user revision.  Deliberately retains the 20.14.151
   application contract while correcting the final presentation regressions. */

/* Brand ribbon: restore the compact, identity-first behavior. Selected artwork
   is untouched; unselected brands recede without tiles, glow or shadows. */
.pulse-report-page #brandSwitcher.brand-switcher{gap:6px!important;align-items:center!important;overflow-y:visible!important}
:root[data-theme] .pulse-report-page #brandSwitcher .portfolio-btn{min-width:96px!important;height:48px!important}
:root[data-theme] .pulse-report-page #brandSwitcher .brand-btn{border:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;text-shadow:none!important;transform:none!important}
/* V20.14.152 -- the single owner of the brand rail's size and state.
   Asked for: "revert this ribbon back as it was (selected should be original
   and unselected should be faded)" and "make brands logo a bit smaller".
   Both were already written here and neither reached the screen, because
   pulse-polish-v150.css declared the same properties with one more class in the
   selector. Those rules are gone; these are the only ones left, so what is
   written here is now what shows. Logos step down 92x58 -> 78x48. */
:root[data-theme] .pulse-report-page #brandSwitcher .brand-btn.logo-only{width:78px!important;height:50px!important;padding:1px 3px!important;opacity:.34!important;filter:saturate(.2) contrast(.9)!important;overflow:visible!important}
/* V20.14.153 -- nothing clips a brand mark.
   Reported: "Red Bull slicer logo is cropped, please make it original". The
   button carried `overflow:hidden`, and the marks do not all sit the same way
   in their files -- Red Bull's fills its canvas to the edges while Corona and
   Rauch carry their own margin -- so at a shared box size Red Bull was the one
   that met the clip. `object-fit:contain` was already preventing any scaling
   distortion; the padding was what left it nothing to breathe into.
   Padding down to 1px/3px, two more pixels of height, and the clip removed
   outright: a mark can now overhang its button rather than lose an edge. */
:root[data-theme] .pulse-report-page #brandSwitcher .brand-btn.logo-only .brand-logo{width:100%!important;height:100%!important;max-width:100%!important;max-height:100%!important;object-fit:contain!important;filter:none!important;box-shadow:none!important}
/* V20.14.198 -- `transform:none!important` used to be in the rule above, and it
   is why the selected brand logo has never floated. V20.14.192 added the float
   (v166-motion.css, @keyframes v192BrandFloat) and it could not run: an
   !important author declaration outranks a CSS animation, so the animated
   transform was discarded on every frame. Nothing looked broken -- the logo
   simply sat still, which is indistinguishable from "the animation was never
   added" unless you go looking.
   The reset still applies to every UNSELECTED logo, which is what it was for --
   normalising per-brand scale tweaks so the rail lines up. The selected one is
   owned by v166-motion.css, which is the file that animates it. */
:root[data-theme] .pulse-report-page #brandSwitcher .brand-btn.logo-only:not(.active) .brand-logo{transform:none!important}
:root[data-theme] .pulse-report-page #brandSwitcher .brand-btn.logo-only.active{opacity:1!important;filter:none!important}
:root[data-theme] .pulse-report-page #brandSwitcher .brand-btn.logo-only:hover{opacity:.78!important;filter:saturate(.72)!important}
:root[data-theme] .pulse-report-page #brandSwitcher .brand-btn.logo-only.active:hover{opacity:1!important;filter:none!important}
.pulse-report-page #brandSwitcher .portfolio-btn{min-width:102px!important;height:58px!important;padding:3px 7px!important;opacity:.45}
.pulse-report-page #brandSwitcher .portfolio-btn.active,.pulse-report-page #brandSwitcher .portfolio-btn:hover{opacity:1}
.pulse-report-page #brandSwitcher .brand-btn.active::after{box-shadow:none!important}

/* New all-portfolio network mark. */
.portfolio-network-icon{display:grid!important;place-items:center;width:46px!important;height:46px!important;border:0!important;background:none!important;box-shadow:none!important;animation:v151PortfolioFloat 3.6s ease-in-out infinite!important}
.portfolio-network-icon svg{width:46px;height:46px;overflow:visible}
.portfolio-network-icon .pni-orbit{fill:none;stroke:currentColor;stroke-width:1;stroke-dasharray:5 4;transform-origin:26px 26px;animation:v151PortfolioOrbit 11s linear infinite}
.portfolio-network-icon .pni-link{fill:none;stroke:currentColor;stroke-width:1.15;opacity:.58}
.portfolio-network-icon .pni-node{fill:var(--cyan);filter:drop-shadow(0 0 4px rgba(0,217,255,.7));animation:v151PortfolioNode 2.2s ease-in-out infinite}
.portfolio-network-icon .pni-node.n2{animation-delay:.35s}.portfolio-network-icon .pni-node.n3{animation-delay:.7s}.portfolio-network-icon .pni-node.n4{animation-delay:1.05s}
.portfolio-network-icon .pni-core{fill:var(--gold);filter:drop-shadow(0 0 5px rgba(255,201,60,.7))}
@keyframes v151PortfolioFloat{50%{transform:translateY(-2px)}}
@keyframes v151PortfolioOrbit{to{transform:rotate(360deg)}}
@keyframes v151PortfolioNode{50%{opacity:.35;transform:scale(.7)}}

/* V20.14.247 -- the Reporting Categories density overrides were removed with
   the old window; see nav-menu.css. */

/* The Agent is a viewport assistant again, outside the command bar. */
#qaFab.qa-fab-floating{position:fixed!important;right:24px!important;bottom:24px!important;left:auto!important;top:auto!important;z-index:1880!important;display:grid!important;place-items:center!important;width:60px!important;height:60px!important;min-width:60px!important;padding:0!important;border:0!important;border-radius:50%!important;background:radial-gradient(circle at 38% 32%,rgba(23,68,102,.96),rgba(3,15,31,.98) 72%)!important;box-shadow:0 16px 38px rgba(0,0,0,.38),0 0 0 1px rgba(78,222,247,.28),0 0 26px rgba(0,217,255,.18)!important;color:#75edff!important;overflow:visible!important}
#qaFab.qa-fab-floating .qa-fab-copy{position:absolute;right:68px;bottom:9px;width:max-content;padding:6px 9px;border-radius:8px;background:var(--bg-panel);border:1px solid var(--bg-panel-line);opacity:0;transform:translateX(5px);pointer-events:none;transition:.18s}
#qaFab.qa-fab-floating:hover .qa-fab-copy,#qaFab.qa-fab-floating:focus-visible .qa-fab-copy{opacity:1;transform:none}
#qaFab.qa-fab-floating .qa-fab-orb,#qaFab.qa-fab-floating svg{display:block;width:52px!important;height:52px!important}
/* V20.14.172 -- the PULSE AGENT mark, in a key per theme.
   Reported: "PULSE AGENT LOGO in white theme not showing properly".
   Measured: the button around it IS themed -- its border goes from #75edff to
   #087fa3 and its glow is toned down -- but the five parts of the mark inside
   were hex literals with no light variant, so a #9af3ff waveform and a
   rgba(101,230,255,.25) halo were being drawn on a near-white orb. In dark the
   mark reads; in light it is a pale smudge, which is exactly the screenshot.
   The colours are tokens on the mark now, so the light theme re-keys them in
   one place instead of each part being restated. The DRAWING is identical --
   same geometry, same animations -- only the key changes. */
.pulse-agent-wave-mark{
  overflow:visible;
  --paw-halo-fill:rgba(0,217,255,.055); --paw-halo-line:rgba(101,230,255,.25);
  --paw-orbit:#67e9ff; --paw-trace:#9af3ff;
  --paw-core:#ffc93c;  --paw-core-glow:rgba(255,201,60,.85);
  --paw-sat:#63e8ff;   --paw-sat-glow:rgba(0,217,255,.9);
}
/* Daylight: the same mark against white. Every stroke moves down to the light
   palette's own deep cyan, and the two glows shrink -- a bloom that reads as
   light on a dark orb reads as a smear on a pale one. */
:root[data-theme="light"] .pulse-agent-wave-mark{
  --paw-halo-fill:rgba(7,185,234,.10); --paw-halo-line:rgba(7,143,197,.42);
  --paw-orbit:#0d8bb0; --paw-trace:#0a6d94;
  --paw-core:#d98400;  --paw-core-glow:rgba(217,132,0,.40);
  --paw-sat:#0d8bb0;   --paw-sat-glow:rgba(7,143,197,.42);
}
.pulse-agent-wave-mark .paw-halo{fill:var(--paw-halo-fill);stroke:var(--paw-halo-line)}
.pulse-agent-wave-mark .paw-orbit{fill:none;stroke:var(--paw-orbit);stroke-width:1.2;stroke-dasharray:6 5;transform-origin:32px 32px;animation:v151AgentOrbit 8s linear infinite}
.pulse-agent-wave-mark .paw-trace{fill:none;stroke:var(--paw-trace);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:60 18;animation:v151AgentTrace 2.7s linear infinite}
.pulse-agent-wave-mark .paw-core{fill:var(--paw-core);filter:drop-shadow(0 0 7px var(--paw-core-glow));animation:v151AgentCore 2s ease-in-out infinite}
.pulse-agent-wave-mark .paw-sat{fill:var(--paw-sat);filter:drop-shadow(0 0 5px var(--paw-sat-glow));transform-origin:32px 32px;animation:v151AgentSat 8s linear infinite}
/* V20.14.212 -- "Make sure that PULSE AGENT icon and animation looks great
   and fancy". The mark keeps every animation it had (orbit, trace, core
   pulse, satellite) and gains an outer RING: a three-colour gradient arc,
   drawn as a dashed circle so it reads as a segment of light, turning slowly
   the opposite way to the orbit so the two never look locked. On hover and
   while the agent is thinking it speeds up. The colours are tokens with a
   daylight set below, because the dark trio is invisible on white. */
.pulse-agent-wave-mark{--paw-ring-a:#00d9ff;--paw-ring-b:#a78bfa;--paw-ring-c:#ffc93c}
:root[data-theme="light"] .pulse-agent-wave-mark{--paw-ring-a:#0096d6;--paw-ring-b:#14b8a6;--paw-ring-c:#f08a00}
.pulse-agent-wave-mark .paw-ring-a{stop-color:var(--paw-ring-a)}.pulse-agent-wave-mark .paw-ring-b{stop-color:var(--paw-ring-b)}.pulse-agent-wave-mark .paw-ring-c{stop-color:var(--paw-ring-c)}
.pulse-agent-wave-mark .paw-ring{fill:none;stroke:url(#pawRingGrad);stroke-width:2.4;stroke-linecap:round;stroke-dasharray:118 74;opacity:.92;transform-origin:32px 32px;animation:v212AgentRing 5.5s linear infinite reverse;filter:drop-shadow(0 0 5px rgba(0,217,255,.45))}
:root[data-theme="light"] .pulse-agent-wave-mark .paw-ring{filter:drop-shadow(0 2px 5px rgba(0,150,214,.42))}
.qa-fab:hover .pulse-agent-wave-mark .paw-ring,body.qa-thinking .pulse-agent-wave-mark .paw-ring{animation-duration:1.6s;stroke-width:3}
@keyframes v212AgentRing{to{transform:rotate(360deg)}}
body.qa-thinking .pulse-agent-wave-mark .paw-orbit,body.qa-thinking .pulse-agent-wave-mark .paw-sat{animation-duration:2.2s!important}body.qa-thinking .pulse-agent-wave-mark .paw-core{fill:var(--paw-sat)}
@keyframes v151AgentOrbit{to{transform:rotate(360deg)}}@keyframes v151AgentTrace{to{stroke-dashoffset:-78}}@keyframes v151AgentCore{50%{transform:scale(.72);transform-origin:32px 32px}}@keyframes v151AgentSat{to{transform:rotate(360deg)}}
html[data-theme="light"] #qaFab.qa-fab-floating{background:radial-gradient(circle at 35% 28%,#fff,#e4f6fb 75%)!important;color:#087fa3!important;box-shadow:0 15px 36px rgba(31,80,110,.2),0 0 0 1px rgba(13,139,176,.2),0 0 24px rgba(0,171,213,.12)!important}

/* Utility icons: one boxless size and baseline. */
#ptbCluster{display:flex!important;align-items:center!important;gap:7px!important}
#ptbCluster .ptb-btn,#ptbCluster .ptb-slot>#themeToggle,#ptbCluster .ptb-slot>button,#ptbCluster .ptb-slot>a,#ptbCluster .ptb-slot .icon-btn,#ptbCluster .ptb-slot .header-icon,#ptbCluster #profileToggle{display:grid!important;place-items:center!important;width:44px!important;height:42px!important;min-width:44px!important;margin:0!important;padding:0!important;border:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important}
#ptbCluster :is(.ptb-btn,.icon-btn,.header-icon,#themeToggle,#profileToggle) svg{width:25px!important;height:25px!important}
#ptbCluster [data-nav-menu] svg,#ptbCluster .ptb-guide-mark{width:29px!important;height:29px!important}

/* Packshots return to the proven compact footprint. Longer Short Item Names
   wrap beside the artwork; they no longer evict products from rows/charts. */
/* V20.14.152 -- the packshot goes back to its documented size, by REMOVAL.
   Asked for: "after increasing the packshots size some items disappeared,
   whether you fix it or revert it back to the old size".
   Two override sheets were both sizing it -- 38x48 here, 32x42 there -- on top
   of a base in pulse-tables.css that is 24x30 for a stated reason: every
   packshot is stored on one 96x120 canvas at 4:5, so the box matches the
   artwork exactly and nothing is scaled to fit. Enlarging the box past the
   canvas is what made rows grow and cells overflow.
   Both overrides are deleted rather than re-tuned. The base rule is the only
   one left, so the size is decided once, where the reason for it is written. */
.sku-label{max-width:100%!important}
/* V20.14.155 -- the ONE rule for the SKU name in a table cell.
   There were two, in this file, 118 lines apart and contradicting each other:
   this one asked for `white-space:normal` with `overflow-wrap:anywhere`, and a
   later one asked for `nowrap` with an ellipsis. Same specificity, but only the
   first carried `!important`, so the first won and the name went on wrapping --
   "still i can see wrapped item name", after a build that reported fixing it.
   I added the second rule without finding the first, which is the same fault
   I had just spent two builds removing from four other stylesheets.
   One rule now, and the later duplicate is deleted rather than out-weighted. */
.sku-label .sku-name{min-width:0!important;white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important;overflow-wrap:normal!important;line-height:1.25!important}
/* V20.14.159 -- the tile now carries the pack AND its distribution figure, so
   it is a two-row grid instead of a centred single cell, and 58px -> 76px to
   hold the second row. Everything the user asked to REMOVE stays removed: no
   border, no radius, no background, no shadow, no name. */
.dd-core-sku{display:inline-grid!important;grid-template-rows:auto auto!important;justify-items:center!important;align-content:start!important;gap:3px!important;width:52px!important;height:76px!important;min-height:0!important;margin:2px 5px!important;padding:0!important;border:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important}
/* The figure is the only text in the panel, so it has to read at a glance
   without turning into a label: tabular figures so a column of packs lines up
   on the decimal, and the accent reserved for the number itself. */
.dd-core-pct{font:700 11px/1 var(--font-mono)!important;font-variant-numeric:tabular-nums;letter-spacing:.02em;color:var(--cyan);opacity:.92;white-space:nowrap}
.dd-core-row{display:flex;flex-wrap:wrap;align-items:flex-start}
.dd-core-packshot{position:relative;display:grid;place-items:center;width:44px;height:54px;background:transparent;border:0;box-shadow:none}
.dd-core-packshot img{display:block;width:36px;height:48px;max-width:36px;max-height:48px;object-fit:contain;filter:drop-shadow(0 6px 6px rgba(0,0,0,.2));transition:transform .18s ease}
.dd-core-packshot:hover img{transform:translateY(-2px) scale(1.06)}
.dd-core-packshot.is-loading i{width:18px;height:18px;border:2px solid var(--cyan-line);border-top-color:var(--cyan);border-radius:50%;animation:v151Spin .7s linear infinite}

/* Persistent KPI row, centred data, and quiet floating glyphs. */
/* V20.14.157 -- `@media screen`. "Keep KPI CARDS there across all pages, as it
   was there before" was a request about the SCREEN, and this rule was granting
   it everywhere -- including on paper, where it outranked the Briefing tab's
   print sheet (which asks for the KPI row to be gone) at (1,3,0) against
   (1,0,0). Printing the Briefing tab therefore dragged the dashboard's KPI row
   onto a document designed without it.
   Printing states its own answer, in the print block further down this file.
   The two questions are no longer answered by one rule. */
@media screen{:root[data-pulse-tab] #kpiRow:not(:empty){display:grid!important}}
#kpiRow .kpi-card,.portfolio-kpi-card{text-align:center!important;justify-items:center!important;align-content:center!important;border-radius:15px!important}
#kpiRow :is(.kpi-head,.kpi-main,.kpi-foot,.kpi-actions),.portfolio-kpi-card :is(.kpi-head,.kpi-main,.kpi-foot){justify-content:center!important;text-align:center!important;width:100%}
.kpi-specific-icon,.kpi-card .kpi-icon,.pkpi-icon{animation:v151KpiFloat 3.4s ease-in-out infinite;filter:drop-shadow(0 6px 8px rgba(0,217,255,.14))}
.kpi-card:nth-child(2) :is(.kpi-specific-icon,.kpi-icon){animation-delay:.4s}.kpi-card:nth-child(3) :is(.kpi-specific-icon,.kpi-icon){animation-delay:.8s}.kpi-card:nth-child(4) :is(.kpi-specific-icon,.kpi-icon){animation-delay:1.2s}
@keyframes v151KpiFloat{50%{transform:translateY(-3px) rotate(1.5deg)}}

/* Mission Control readability and a fully frozen command deck. */
.mc-telemetry,.mc-telemetry :is(span,b,small),.pulse-report-page :is(.klabel,.psub,.flabel,.fselect,.tab-btn,.filter-pill){font-size:max(10.5px,var(--fs-2xs,10.5px))}
/* V20.14.193 -- THE STICKY OFFSET WAS COUNTING A BAR THAT IS NOT IN ITS WAY.

   `top:var(--mc-bar-h)` was 52px of clearance for the portal's fixed top bar.
   But this header sticks inside #mainShell, which has `overflow-y:auto` and so
   is the scroll container -- and #mainShell's own box already starts BELOW that
   bar. The offset was therefore clearance for something that had already been
   cleared: the header floats a further 52px down inside its own scrollport.

   On a wide screen nothing shows, because the deck's natural position is below
   52px anyway and the offset never engages -- which is exactly why this was
   never reproduced above 768px. On a phone the deck is 239-496px tall and its
   natural position inside the scrollport is above 52, so the offset does
   engage: the header is pushed down over the content that follows it and the
   first heading of the first section sits underneath it before the reader has
   scrolled at all.

   Measured at 1366 and at 360/390/430/480, before and after:

       width   as-is (gap between header and #tabContent)   with top:0
       360     -40px   (overlap)                             +12px
       390     -40px   (overlap)                             +12px
       430     -40px   (overlap)                             +12px
       480     -40px   (overlap)                             +12px
       1366    +12px                                         +12px

   So this is not a mobile patch and not a reversal of the frozen-deck request:
   the deck stays sticky at every width, and the desktop layout is byte-for-byte
   what it was. It is the removal of a double-count. */
/* V20.14.200 -- the deck stops underneath the fixed telemetry strip.
   V20.14.193 removed an offset here and was right to: the offset it removed was
   the deck's OWN top bar, which lives inside this element, so offsetting by it
   double-counted and pushed 40px of header over the first section heading.
   What that build did not separate is that there are TWO bars, and only one of
   them is inside. pulse-mission.js's telemetry strip is `position: fixed;
   top: 0; z-index: 1500` -- outside this element and above it -- so the deck
   really does slide under that one, and the toggles went with it.
   The offset is --mc-bar-h, which pulse-v90.css already defines as that bar's
   height (52px) and which twelve other rules already use to clear it -- the
   Control Panel shell, the notification drawer, the scope indicator, the page's
   own body padding. The deck was the ONE thing not using it. This is not a new
   number; it is the deck rejoining the ones that were already right. It falls
   back to 0 wherever the variable is undefined, which is the pre-V20.14.200
   behaviour on pages with no such bar. */
.pulse-sticky-header{position:sticky!important;top:var(--mc-bar-h,0px)!important;z-index:520!important}
.pulse-sticky-header.is-condensed .brand-switcher{display:flex!important}.pulse-sticky-header.is-condensed .filterbar{display:flex!important}.pulse-sticky-header.is-condensed .deck-summary{display:none!important}

/* Every chart title receives the icon injected by dashboard.js; keep the
   movement small enough to aid wayfinding without fighting the data. */
.ptitle>.pcard-icon,.v150-title-icon{display:inline-grid;place-items:center;vertical-align:-6px;animation:v151TitleFloat 3.8s ease-in-out infinite}
.ptitle>.pcard-icon svg,.v150-title-icon svg{overflow:visible;filter:drop-shadow(0 0 4px rgba(0,217,255,.25))}
.ptitle>.pcard-icon :is(path,circle,polyline,line),.v150-title-icon :is(path,circle,polyline,line){stroke-dasharray:52;animation:v151TitleDraw 5s ease-in-out infinite}
@keyframes v151TitleFloat{50%{transform:translateY(-1.5px)}}@keyframes v151TitleDraw{0%,64%,100%{stroke-dashoffset:0}78%{stroke-dashoffset:52}}

/* Targets: truly centred, with lower-contrast internal grids. */
.tgt-table th,.tgt-table td,.tgt-table .tgt-name{text-align:center!important;vertical-align:middle!important}
.tgt-table :is(th,td),.tgt-table tfoot td{border-color:color-mix(in srgb,var(--bg-panel-line) 52%,transparent)!important}
.tgt-table tbody tr:hover td{background:color-mix(in srgb,var(--cyan) 4%,transparent)!important}

/* Footprint is one composed instrument: larger map and coverage rail within a
   shared atmospheric frame, side by side until the responsive breakpoint. */
.fp-panel .fp-body{grid-template-columns:minmax(0,1fr) minmax(320px,360px)!important;gap:16px!important;padding:14px!important;border:1px solid var(--bg-panel-line);border-radius:18px;background:radial-gradient(circle at 20% 15%,rgba(0,217,255,.075),transparent 42%),linear-gradient(145deg,var(--bg-panel-hi),var(--bg-panel));box-shadow:inset 0 1px rgba(255,255,255,.035),0 18px 46px rgba(0,0,0,.12)}
.fp-panel .fp-map-frame{height:clamp(500px,74vh,830px)!important;border-radius:16px!important;background:radial-gradient(circle at 48% 42%,rgba(17,90,124,.2),transparent 58%),var(--bg-panel-hi)!important;box-shadow:inset 0 0 65px rgba(0,5,18,.18),0 12px 28px rgba(0,0,0,.13)}
.fp-panel .fp-rail{align-self:stretch;align-content:start}.fp-panel .fp-card{border-radius:14px!important;background:color-mix(in srgb,var(--bg-panel-hi) 92%,transparent)!important;box-shadow:0 10px 26px rgba(0,0,0,.09)}

/* Briefing bullets are live wayfinding marks; the existing section glyphs and
   every point title now share one restrained signal animation. */
.briefing-sec-icon{animation:v151BriefIcon 3.4s ease-in-out infinite}.briefing-list>li::before{box-shadow:0 0 0 0 color-mix(in srgb,var(--cyan) 34%,transparent);animation:v151BriefPoint 2.6s ease-out infinite}
@keyframes v151BriefIcon{50%{transform:translateY(-2px);filter:drop-shadow(0 0 5px rgba(0,217,255,.35))}}@keyframes v151BriefPoint{65%{box-shadow:0 0 0 7px transparent}}

/* Deliberately attractive, but bounded, What-if affordance. */
.v21-scenario-btn,.v21-suggest-btn,[data-open-scenario]{animation:v151WhatIf 2.7s ease-in-out infinite!important}
/* V20.14.483 -- the float kept, its glow no longer pulsed: a box-shadow in the keyframes re-painted the header's two buttons every frame on every page */
@keyframes v151WhatIf{50%{transform:translateY(-2px)}}

/* Use the PULSE mark, rather than a generic CSS ring, while a filter/scope is
   being calculated. */
.scope-update-indicator>i{width:22px!important;height:22px!important;border:0!important;border-radius:0!important;background:url('/assets/pulse-mark.svg?v=20.14.530') center/contain no-repeat!important;animation:v151Spin .9s linear infinite!important;filter:drop-shadow(0 0 6px rgba(0,217,255,.45))}
@keyframes v151Spin{to{transform:rotate(360deg)}}

/* Compact, animated Find-by-brand / command search. */
.value-search-overlay{padding-top:min(10vh,78px)!important;backdrop-filter:blur(10px)!important}
.value-search-dialog{width:min(620px,calc(100vw - 24px))!important;max-height:min(640px,72vh)!important;border-radius:15px!important;animation:v151SearchIn .28s cubic-bezier(.16,1,.3,1) both}
.value-search-head{padding:11px 15px 6px!important}.value-search-head h2{font-size:17px!important}.value-search-field{margin:0 15px 6px!important}
#valueSearchInput{padding-top:10px!important;padding-bottom:10px!important;font-size:14px!important;border-radius:9px!important}
.value-search-results{max-height:min(40vh,360px)!important;padding:0 9px 6px!important}.value-search-group{margin-top:3px!important}.value-search-group h3{padding:5px 8px 3px!important}.value-search-result{padding:6px 8px!important;gap:9px!important;border-radius:8px!important}.value-search-dialog footer{padding:7px 15px!important}
/* V20.14.164 -- the second owner of the search mark's motion, removed.
   This file animated .vsb-sweep and .vsb-wave at 2.8s and 2.1s;
   v104-value-features.css animated the same two classes at 3.1s. Which pair
   actually ran was decided by stylesheet order, not by a choice. The mark is
   in the icon library now and pulse-mission.css drives the whole rail. */
@keyframes v151SearchIn{from{opacity:0;transform:translateY(-12px) scale(.96)}to{opacity:1;transform:none}}

/* Luminous light workspace: smooth geometry, layered light and legible chart
   surfaces. This is a visual skin only; no component is remounted. */
html[data-theme="light"] .pulse-report-page{background:radial-gradient(circle at 12% 5%,rgba(0,174,215,.11),transparent 32%),radial-gradient(circle at 88% 18%,rgba(120,87,255,.08),transparent 34%),linear-gradient(155deg,#f8fcff,#eef7fb 56%,#f8f6ff)!important}
html[data-theme="light"] .pulse-report-page :is(.panel,.kpi-card,.filterbar,.tabnav,.dd-panel,.dd-tile,.v21-map-panel,.fp-summary,.tgt-section){border-color:rgba(19,126,164,.16)!important;border-radius:16px!important;background:linear-gradient(145deg,rgba(255,255,255,.96),rgba(239,249,253,.92))!important;box-shadow:0 13px 32px rgba(35,80,112,.09),inset 0 1px rgba(255,255,255,.9)!important}
html[data-theme="light"] .pulse-report-page :is(.ptitle,.dd-title,.kpi-card b,.kpi-card .kval){color:#102b49!important}
html[data-theme="light"] .pulse-report-page :is(.psub,.klabel,.dd-sub,.chart-note){color:#536f89!important}
html[data-theme="light"] .value-lens-btn.active{color:#006b8f!important;border-color:#087fa3!important}
html[data-theme="light"] .fp-panel .fp-body{background:radial-gradient(circle at 22% 18%,rgba(0,173,213,.13),transparent 44%),linear-gradient(145deg,rgba(255,255,255,.96),rgba(229,244,250,.9))!important;box-shadow:0 16px 40px rgba(35,79,109,.1),inset 0 1px #fff}

/* Login: light mode belongs only to the sign-in half. The animated Saudi map
   deliberately keeps the original dark command-map palette, including the
   moving scan, route and Red Bull vehicle. Earlier in this revision a later
   rule accidentally repainted the map pale and overrode the correct v42
   treatment from pulse-light-orbit.css. Restate the dark palette here because
   this file loads last. */
:root[data-theme="light"] body.pulse-login-page .illustration-side{--pulse-bg-void:#070c16;--pulse-bg-deep:#0a1930;--pulse-bg-panel:#111f38;--pulse-bg-panel-hi:#16294a;--pulse-line:#1c2f4f;--pulse-text-hi:#eaf1ff;--pulse-text-mid:#8b9bb4;--pulse-text-dim:#526080;--pulse-gold:#ffc93c;--pulse-cyan:#00d9ff;color:#eaf1ff!important;background:#0a1930!important}
:root[data-theme="light"] body.pulse-login-page .illustration-side::before{background:radial-gradient(ellipse 900px 700px at 25% 25%,rgba(0,217,255,.12),transparent 55%)!important;animation:bgWaveCyan 17s ease-in-out infinite!important}
:root[data-theme="light"] body.pulse-login-page .illustration-side::after{background:radial-gradient(ellipse 800px 600px at 78% 80%,rgba(255,201,60,.08),transparent 55%)!important;animation:bgWaveGold 21s ease-in-out infinite!important}
:root[data-theme="light"] body.pulse-login-page .illo-edge-fade{background:linear-gradient(to right,transparent,#0a1930 92%)!important}
:root[data-theme="light"] body.pulse-login-page .ksa-outline{fill:#16294a!important;fill-opacity:.55!important;stroke:url(#mapStroke)!important;stroke-width:.22!important;filter:none!important}
:root[data-theme="light"] body.pulse-login-page .ksa-glow-path{fill:none!important;stroke:#00d9ff!important;stroke-width:1.6!important;opacity:.55!important;filter:url(#mapBlur)!important}
:root[data-theme="light"] body.pulse-login-page .ksa-scan-rect{opacity:1!important;animation:ksaScan 5s ease-in-out infinite!important}
:root[data-theme="light"] body.pulse-login-page .ksa-node-label{fill:#8b9bb4!important}
:root[data-theme="light"] body.pulse-login-page .ksa-hub-label{fill:#ffc93c!important}

/* Generic management-pack printing must override Briefing's sheet-only rules;
   this class is present only for the user-requested current-tab export. */
/* V20.14.157 -- the COLOURS are gone from this block, and that is the point.
   It used to force `background:#fff;color:#111` onto every panel, competing
   with a rule in v23-quality-pass.js that forced the dark theme's colours,
   at identical specificity and identical !important -- so paper was decided
   by which sheet happened to load last rather than by anyone's intention.
   Printing switches to the designed light theme now (enterPrintTheme in
   dashboard.js), which is contrast-checked against white and legible with
   background graphics off. So there is nothing here to state about colour:
   the theme already says it, once, in tokens.
   What remains is LAYOUT, which no theme has an opinion about -- the report's
   screen scaffolding unwrapped onto a page, and cards kept off page breaks. */
/* V20.14.157 -- every selector in this block is scoped `:not(:has(.briefing-page))`,
   and that is the fix for the PDF Ramy sent.

   The Briefing tab is already a complete, designed print document: pulse-briefing.css
   strips the application off the page ("print by REMOVING the application, not by
   hiding it") and lays out an ink sheet with its own colours. This block is a
   DIFFERENT print document -- "export the current tab as a management pack" -- and
   it was applying on the Briefing tab as well. Two print designs, one page, and
   this one wins on specificity:

     briefing: #tabBody > *:not(.briefing-page) { display:none }   (1,1,0)
     here:     body.pulse-print-tab #tabBody > * { display:block }  (1,1,1)  <- wins
     briefing: ... , #kpiRow , ...                { display:none }  (1,0,0)
     here:     body.pulse-print-tab #kpiRow:not(:empty){display:grid}(1,2,1)  <- wins

   So the dashboard KPI row and the collapsed brief printed ON TOP of the briefing
   sheet -- dark cards over a light document, overlapping its header. Measured on
   the Briefing tab in print media: every other element the briefing sheet hides
   was correctly hidden; exactly these two were not.
   That is a regression from "Keep KPI CARDS there across all pages" in V20.14.152.
   The request was about the screen, and the rule that delivered it did not stop
   at the screen.
   A tab that brings its own print design owns its page; this block covers the
   seventeen that do not. */
@media print{
  body.pulse-print-tab:not(:has(.briefing-page)) :is(#mainShell,#tabContent,#tabBody,.shell){display:block!important;width:auto!important;max-width:none!important;margin:0!important;padding:0!important}
  body.pulse-print-tab:not(:has(.briefing-page)) #tabBody>*{display:block!important}
  body.pulse-print-tab:not(:has(.briefing-page)) #kpiRow:not(:empty){display:grid!important}
  body.pulse-print-tab:not(:has(.briefing-page)) :is(.panel,.kpi-card){break-inside:avoid;page-break-inside:avoid;box-shadow:none!important}
  body.pulse-print-tab:not(:has(.briefing-page)) :is(canvas,svg){visibility:visible!important}
}

@media(max-width:1100px){.fp-panel .fp-body{grid-template-columns:1fr!important}.fp-panel .fp-map-frame{height:clamp(430px,64vh,680px)!important}}
@media(max-width:760px){
  .pulse-report-page #brandSwitcher.brand-switcher{gap:2px!important}.pulse-report-page #brandSwitcher .brand-btn.logo-only{width:76px!important;height:52px!important}.pulse-report-page #brandSwitcher .portfolio-btn{min-width:84px!important;height:52px!important}.portfolio-network-icon,.portfolio-network-icon svg{width:40px!important;height:40px!important}
  #qaFab.qa-fab-floating{right:14px!important;bottom:14px!important;width:54px!important;height:54px!important;min-width:54px!important}#qaFab.qa-fab-floating .qa-fab-orb,#qaFab.qa-fab-floating svg{width:47px!important;height:47px!important}
  #ptbCluster{gap:2px!important}#ptbCluster .ptb-btn,#ptbCluster .ptb-slot>button,#ptbCluster .ptb-slot>a,#ptbCluster #themeToggle,#ptbCluster #profileToggle{width:36px!important;min-width:36px!important;height:38px!important}#ptbCluster :is(.ptb-btn,.icon-btn,.header-icon,#themeToggle,#profileToggle) svg{width:22px!important;height:22px!important}
  .fp-panel .fp-body{padding:8px!important;border-radius:14px!important}.fp-panel .fp-map-frame{height:450px!important}
}

:root.pulse-motion-off :is(.portfolio-network-icon,.portfolio-network-icon *,.pulse-agent-wave-mark *,.kpi-specific-icon,.kpi-icon,.pkpi-icon,.pcard-icon,.pcard-icon *,.v150-title-icon,.v150-title-icon *,.briefing-sec-icon,.briefing-list>li::before,.v21-scenario-btn,.v21-suggest-btn,[data-open-scenario],.value-search-button *,.scope-update-indicator>i){animation:none!important;transition:none!important}
@media(prefers-reduced-motion:reduce){.pulse-agent-wave-mark .paw-ring{animation:none}}
@media(prefers-reduced-motion:reduce){:is(.portfolio-network-icon,.portfolio-network-icon *,.pulse-agent-wave-mark *,.kpi-specific-icon,.kpi-icon,.pkpi-icon,.pcard-icon,.pcard-icon *,.v150-title-icon,.v150-title-icon *,.briefing-sec-icon,.briefing-list>li::before,.v21-scenario-btn,.v21-suggest-btn,[data-open-scenario],.value-search-button *,.scope-update-indicator>i),body.qa-thinking .pulse-agent-wave-mark *,body.qa-thinking .pulse-agent-wave-mark :is(.paw-orbit,.paw-sat,.paw-core){animation:none!important;transition:none!important}}

/* V20.14.152 -- the SKU name sits BESIDE its packshot, on one line.
   Asked for: "make sure that item name besides packshots is compact as it takes
   2 lines". Measured on the SKU tab: 7 of 7 labels wrapped. The label is an
   inline-flex holding a fixed-width picture and a name that was free to wrap in
   whatever width was left, so the longer the name the taller every row in the
   table became -- the same shape of fault as the outlet cell fixed in
   V20.14.147, where a name above a code doubled 21 scorecard rows.
   The name gets its own line-box that does not wrap and an ellipsis when it
   genuinely cannot fit; the full name stays available as the cell's title. */
.sku-label{align-items:center!important;min-width:0!important}
/* V20.14.155 -- the duplicate that used to live here is merged into the rule above. */
.dtable td .sku-label,.dd-table td .sku-label{white-space:nowrap!important}


/* ===========================================================================
   V20.14.190 -- THE CONDENSED STRIP, SIZED FOR SCROLLING PAST.
   ===========================================================================
   This file is the last word on the deck header, because line 160 is a
   revision that was asked for: when the deck condenses, the brand rail and the
   filter bar STAY, instead of collapsing into the compact summary this skin
   would otherwise show.

   That request is kept. What it costs is now measured: while scrolling, the
   sticky deck's bottom edge sat at 298px on a 1366x768 laptop, leaving 470px
   of reading area for panels that are 470-550px tall -- which is why no chart
   was ever fully in view, on any tab, at any scroll position.

   So the two rows stay and get smaller once you are past the top: a brand rail
   you scroll past does not need 50px logos, and a filter bar you are not
   currently filtering with does not need 30px selects. Both go back to full
   size the moment you scroll back up.

   Specificity matches the rules above deliberately -- these are the same
   selectors, not a louder version of them. */
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed #brandSwitcher.brand-switcher { gap: 4px !important; margin-bottom: 3px !important; }
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed #brandSwitcher .brand-btn.logo-only { width: 62px !important; height: 34px !important; padding: 0 2px !important; }
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed #brandSwitcher .portfolio-btn { min-width: 68px !important; height: 34px !important; }
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed .portfolio-network-icon,
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed .portfolio-network-icon svg { width: 26px !important; height: 26px !important; }
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed .filterbar { padding: 3px 10px !important; gap: 6px !important; }
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed .filterbar select.fselect { min-height: 26px !important; padding-top: 3px !important; padding-bottom: 3px !important; }
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed .filterbar .v164-rail button { min-height: 24px !important; padding: 3px 6px !important; }
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed .filterbar .v20-control,
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed .filter-reset { min-height: 26px !important; padding: 3px 8px !important; }
:root[data-theme] .pulse-report-page .pulse-sticky-header.is-condensed .topbar { padding-top: 2px !important; padding-bottom: 1px !important; }
