/* ridge.css v1 — the Ridge Ratings design system. ONE file, ONE :root, every component in the contract.
   Fnn = research.json .confirmed[nn-1]. Cascade: tokens are plain :root; everything else sits in @layer ridge,
   so any unlayered page rule (a rebuilt page's own <style>, or a legacy page's :root/component CSS) wins
   regardless of order — legacy pages cannot break when nav.js v19 loads this file (F03/F30). Only the focus
   ring and the print sheet are unlayered on purpose. Grade tokens: --g-x fill, --g-x-t tint, --g-x-i ink. */
@layer ridge;

/* 1. TOKENS — one :root (F26 contrast-safe greys, F29 one grade scale, F28 radii, F34 reserved chrome heights) */
:root{
--paper:#F6F2E9;--panel:#FFFFFF;--panel-2:#F9F5EC;--gold-tint:#F4ECD8;--ink-panel:#1C2A36;
--ink:#1C2A36;--ink-2:#3E4C59;--dim:#5F6975;--disabled:#9A9484;
--edge:#E3DCCB;--edge-2:#CFC5AE;--edge-ctl:#A89F8C;
--gold:#9C7C2E;--gold-2:#7A5F1E;--gold-light:#C9A24B;--up:#2F7D57;--down:#B4453E;--warn:#8A5A12;--flat:var(--dim);
--serif:'Fraunces','Fraunces Fallback',Georgia,serif;--sans:'Inter','Inter Fallback',-apple-system,'Segoe UI',sans-serif;--mono:'IBM Plex Mono','SF Mono',Menlo,Consolas,monospace;
--g-aaa:#1F6B45;--g-aa:#2F7D57;--g-a:#5E8C3A;--g-baa:#9C7C2E;--g-ba:#B8892E;--g-b:#A85C2A;--g-caa:#B4453E;--g-nr:#8A8F96;
--g-aaa-t:#E3F1E9;--g-aa-t:#E6F2EA;--g-a-t:#EAF0DF;--g-baa-t:#F4ECD8;--g-ba-t:#F6EDD9;--g-b-t:#F5E5DA;--g-caa-t:#F6E2DF;--g-nr-t:#ECEDEF;
--g-aaa-i:#17472F;--g-aa-i:#1E5A3E;--g-a-i:#3E5F24;--g-baa-i:#6B531D;--g-ba-i:#74551C;--g-b-i:#6E3A18;--g-caa-i:#7E2E28;--g-nr-i:#4E545B;
--r-sm:6px;--r-md:8px;--r-lg:12px;--shadow-2:0 12px 32px rgba(28,42,54,.10);
--w-container:1200px;--w-doc:900px;--w-prose:720px;--gutter:clamp(16px,4vw,32px);
--masthead-h:64px;--band-h:44px;--tabbar-h:56px;--safe-b:env(safe-area-inset-bottom,0px);
color-scheme:light}
@media(max-width:760px){:root{--masthead-h:56px}}
@media(max-width:480px){:root{--band-h:80px}}   /* two lines on a phone: the meta line has a row of its own */

@layer ridge{
/* 2. RESET (F09/F14/F24: nothing may be wider than its parent — min-width:0 on every grid/flex child) */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;font-optical-sizing:auto;scroll-padding-top:calc(var(--masthead-h) + 16px)}
body{margin:0;background:var(--paper);color:var(--ink);-webkit-font-smoothing:antialiased}
body.page{font:400 15px/23px var(--sans)}   /* typography is opted into by .page so legacy pages keep their own rhythm */
img{max-width:100%;height:auto}svg{max-width:100%}
.grid>*,.flex>*,.kpi-row>*,.rr-band>*,.rowcard>*{min-width:0}
.page :where(button,input,select,textarea){font:inherit;color:inherit;margin:0}
.page :where(button){cursor:pointer}
:where(.page h1,.page h2,.page h3,.page h4){margin:0;font-weight:600}
.page :where(p){margin:0 0 12px}.page :where(p:last-child){margin-bottom:0}
.page :where(ul,ol){margin:0 0 12px;padding-left:20px}
.page :where(a){color:var(--ink);text-decoration:underline;text-decoration-color:var(--gold-2);text-decoration-thickness:1px;text-underline-offset:3px}
.page :where(a:hover){color:var(--gold-2)}
.page :where(strong,b){font-weight:600}
.page :where(hr){border:0;border-top:1px solid var(--edge-2);margin:32px 0}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* 3. TYPE SCALE (F26: nothing under 10px; F27: Fraunces = headings, grade letter, index value only; Inter = UI + prose; mono = labels, IDs, code) */
.display-1{font:600 56px/60px var(--serif);letter-spacing:-.015em;font-variation-settings:'opsz' 144}
.display-2{font:600 40px/44px var(--serif);letter-spacing:-.01em;font-variation-settings:'opsz' 144}
.h2,:where(.page h2){font:600 24px/30px var(--serif);font-variation-settings:'opsz' 72;letter-spacing:-.005em}
.h3,:where(.page h3){font:600 17px/24px var(--sans)}
:where(.page h4){font:600 15px/23px var(--sans)}
.lede{font:400 17px/26px var(--sans);max-width:58ch;color:var(--ink-2)}
.body{font:400 15px/23px var(--sans)}.body-s{font-size:13px;line-height:19px}
.kicker,.label{font:500 11px/16px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--ink-2)}
.micro{font:400 11px/16px var(--mono);letter-spacing:.05em;color:var(--dim)}
.tnum,.tbl,.tile,.rr-band,.seal,.kpi-row{font-variant-numeric:tabular-nums}
.index-value{font:600 44px/48px var(--serif);font-variation-settings:'opsz' 144;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.grade-xl{font:700 64px/1 var(--serif)}.grade-lg{font:700 44px/1 var(--serif)}.grade-md{font:700 28px/1 var(--serif)}.grade-sm{font:700 16px/1 var(--serif)}
.up{color:var(--up)}.down{color:var(--down)}.warn{color:var(--warn)}.dim{color:var(--dim)}.ink-2{color:var(--ink-2)}.gold{color:var(--gold-2)}
.right{text-align:right}.center{text-align:center}.nowrap{white-space:nowrap}
@media(max-width:760px){.display-1{font-size:46px;line-height:50px}.display-2{font-size:30px;line-height:34px}.h2,:where(.page h2){font-size:21px;line-height:26px}.lede{font-size:16px;line-height:24px}}
@media(max-width:480px){.display-1{font-size:38px;line-height:42px}}

/* 4. CONTAINERS, GRID, SPACING (F14: ≥16px side gutter at every width; 8px scale; one 760 boundary + 480) */
.container,.container--doc,.container--prose{width:100%;max-width:calc(var(--w-container) + 2*var(--gutter));margin-inline:auto;padding-inline:var(--gutter)}
.container--doc{max-width:calc(var(--w-doc) + 2*var(--gutter))}.container--prose{max-width:calc(var(--w-prose) + 2*var(--gutter))}
.grid{display:grid;gap:24px}.grid--2{grid-template-columns:repeat(2,1fr)}.grid--3{grid-template-columns:repeat(3,1fr)}.grid--4{grid-template-columns:repeat(4,1fr)}
.grid--7-5{grid-template-columns:7fr 5fr}.grid--8-4{grid-template-columns:8fr 4fr}.grid--9-3{grid-template-columns:9fr 3fr}
.flex{display:flex;flex-wrap:wrap;gap:16px;align-items:center}.flex--between{justify-content:space-between}
.stack>*+*{margin-top:16px}.stack--s>*+*{margin-top:8px}
.section{padding-block:64px}.section--s{padding-block:48px}
.mt-8{margin-top:8px}.mt-16{margin-top:16px}.mt-24{margin-top:24px}.mt-32{margin-top:32px}.mt-48{margin-top:48px}.mb-16{margin-bottom:16px}.mb-24{margin-bottom:24px}
/* the same utilities at (0,2,0): a one-class utility LOSES to `.prose p` (0,1,1), so a <p class="lede mt-16">
   inside .prose rendered with no top margin at all (measured on /governance: h1 bottom 256, p top 256) */
.page .mt-8{margin-top:8px}.page .mt-16{margin-top:16px}.page .mt-24{margin-top:24px}.page .mt-32{margin-top:32px}.page .mt-48{margin-top:48px}.page .mb-16{margin-bottom:16px}.page .mb-24{margin-bottom:24px}
@media(min-width:761px){.hide-d{display:none!important}}
@media(max-width:1024px){.grid--7-5,.grid--8-4,.grid--9-3{grid-template-columns:1fr}}
@media(max-width:760px){.grid{gap:12px}.grid--3,.grid--4{grid-template-columns:repeat(2,1fr)}.section{padding-block:28px}.section--s{padding-block:24px}.hide-m{display:none!important}}
@media(max-width:480px){.grid--2,.grid--3,.grid--4{grid-template-columns:1fr}}

/* 5. MASTHEAD .rr-masthead (F30 one canonical masthead from nav.js; F34 56px on phones; sticky, opaque, 1px rule). nav.js fills #rr-masthead. */
#rr-masthead{min-height:var(--masthead-h)}
#rr-masthead,.rr-masthead{position:sticky;top:0;z-index:50}
.rr-masthead{height:var(--masthead-h);background:var(--paper);border-bottom:1px solid var(--edge-2)}
.rr-masthead__in{height:100%;display:flex;align-items:center;gap:16px}
.rr-masthead__wm{display:flex;flex-direction:column;justify-content:center;gap:2px;min-height:40px;font:600 22px/1 var(--serif);color:var(--ink);text-decoration:none;white-space:nowrap;letter-spacing:-.01em}
.rr-masthead__wm small{font:500 11px/13px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--ink-2)}
.rr-masthead__nav{display:flex;align-items:center;gap:2px;list-style:none;margin:0 0 0 8px;padding:0}
.rr-masthead__nav li{position:relative}
.rr-masthead__nav a,.rr-masthead__nav button{display:inline-flex;align-items:center;gap:4px;height:36px;padding:0 11px;border:0;border-radius:var(--r-sm);background:none;font:500 14px/20px var(--sans);color:var(--ink-2);text-decoration:none;white-space:nowrap}
.rr-masthead__nav a:hover,.rr-masthead__nav button:hover{color:var(--ink);background:var(--panel-2)}
.rr-masthead__nav a[aria-current],.rr-masthead__nav a.on{color:var(--ink);font-weight:600;box-shadow:inset 0 -2px 0 var(--gold);border-radius:var(--r-sm) var(--r-sm) 0 0}
.rr-menu{position:absolute;top:100%;left:0;min-width:220px;margin:4px 0 0;padding:6px;list-style:none;background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-md);box-shadow:var(--shadow-2);display:none;z-index:55}
.rr-masthead__nav li:hover>.rr-menu,.rr-masthead__nav li:focus-within>.rr-menu,.rr-menu.is-open{display:block}
.rr-menu a{display:flex;height:36px;padding:0 10px;font-weight:400}
.rr-masthead__right{margin-left:auto;display:flex;align-items:center;gap:6px}
.rr-masthead__link{font:500 14px/20px var(--sans);color:var(--ink-2);text-decoration:none;padding:8px 10px;border-radius:var(--r-sm)}
.rr-masthead__link:hover{color:var(--ink);background:var(--panel-2)}
.rr-masthead__ic{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border:0;border-radius:var(--r-sm);background:none;color:var(--ink)}
.rr-masthead__ic:hover{background:var(--panel-2)}.rr-masthead__ic svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.8}
.rr-masthead__stamp{font:400 11px/16px var(--mono);letter-spacing:.06em;color:var(--dim);white-space:nowrap}
.rr-scrim{position:fixed;inset:0;background:rgba(28,42,54,.35);z-index:58}
.rr-sheet{position:fixed;left:0;right:0;bottom:0;z-index:59;max-height:82vh;overflow:auto;padding:12px var(--gutter) calc(16px + var(--safe-b));background:var(--panel);border-radius:var(--r-lg) var(--r-lg) 0 0;box-shadow:var(--shadow-2)}
.rr-sheet ul{list-style:none;margin:0;padding:0}.rr-sheet a{display:flex;align-items:center;min-height:48px;padding:0 4px;border-bottom:1px solid var(--edge);font:500 16px/22px var(--sans);color:var(--ink);text-decoration:none}
.rr-sheet .kicker{display:block;margin:16px 0 4px}
@media(max-width:760px){.rr-masthead__nav,.rr-masthead__stamp,.rr-masthead__link,.rr-masthead__right .btn{display:none}.rr-masthead__wm{font-size:20px}.rr-masthead__wm small{display:none}}

/* 6. INDEX BAND .rr-band (F11/F13/F15: one server-rendered print, identical on every page, visible without JS; two lines ≤480) */
.rr-band-slot{min-height:var(--band-h)}
.rr-band{display:flex;flex-wrap:wrap;align-items:center;gap:4px 14px;min-height:var(--band-h);padding:6px max(var(--gutter),calc((100% - var(--w-container))/2));background:var(--panel-2);border-bottom:1px solid var(--edge-2);font:400 13px/18px var(--sans);color:var(--ink-2)}
.rr-band__name{font:500 11px/16px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--ink-2)}
.rr-band__v{font:600 20px/24px var(--serif);color:var(--ink);letter-spacing:-.01em}
.rr-band__d{font-weight:500;white-space:nowrap}.rr-band__d.up{color:var(--up)}.rr-band__d.down{color:var(--down)}.rr-band__d.flat{color:var(--dim)}
/* NEVER nowrap/ellipsis: this line is the only place {{NEXT_RELEASE}} appears on every page, and at ≤480 an
   ellipsis ate it (measured /pulse at 390: clientW 245 vs scrollW 291). It wraps instead, at every width. */
.rr-band__meta{flex:1 1 auto;min-width:0;font-size:12px;color:var(--dim)}
.rr-band__spark{width:96px;height:24px;flex:0 0 auto}
.rr-band__verify{margin-left:auto;padding-block:11px;margin-block:-11px;font:500 13px/18px var(--sans);color:var(--ink);text-decoration:underline;text-decoration-color:var(--gold-2);text-underline-offset:3px;white-space:nowrap}
.rr-band__verify:hover{color:var(--gold-2)}
@media(max-width:760px){.rr-band__spark{display:none}}
/* ≤480: RDRPI / value / YoY / MoM fill the first row, so the meta line and the verify link share the second
   (the meta wraps inside it — it is never clipped). A 60% flex-basis is what keeps them on one line together:
   at 100% the link was pushed to a row of its own between the value and the meta, stranded in the middle. */
@media(max-width:480px){.rr-band{gap:2px 10px;padding-block:8px}.rr-band__meta{flex:1 1 60%;order:5;font-size:11px}.rr-band__verify{order:6;flex:0 0 auto;margin-left:auto;font-size:12px}}

/* 7. BOTTOM TAB BAR .rr-tabbar (F35: five fixed tabs share the width, 11px labels, fits 320px; body reserves its height) */
.rr-tabbar{display:none;position:fixed;left:0;right:0;bottom:0;z-index:60;height:calc(var(--tabbar-h) + var(--safe-b));padding:0 0 var(--safe-b);background:var(--paper);border-top:1px solid var(--edge-2)}
.rr-tabbar a{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;padding:5px 2px 4px;margin-top:-1px;border-top:2px solid transparent;font:500 11px/14px var(--sans);letter-spacing:0;color:var(--ink-2);text-decoration:none;white-space:nowrap}
.rr-tabbar a svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.8}
.rr-tabbar a[aria-current],.rr-tabbar a.on{color:var(--ink);font-weight:600;border-top-color:var(--gold)}
@media(max-width:760px){.rr-tabbar{display:flex}body.page,body.legacy{padding-bottom:calc(var(--tabbar-h) + var(--safe-b))}}

/* 8. FOOTER .rr-footer (one snippet on every page; 4 → 2 → 1 columns; the single independence line lives here) */
.rr-footer{margin-top:64px;padding-block:40px 32px;border-top:1px solid var(--edge-2);background:var(--paper);font:400 13px/19px var(--sans);color:var(--ink-2)}
.rr-footer__cols{display:grid;grid-template-columns:repeat(4,1fr);gap:32px 24px}
.rr-footer__col ul{list-style:none;margin:0;padding:0}.rr-footer__col li{margin:0 0 8px}
.rr-footer__col .kicker{display:block;margin-bottom:12px}
.rr-footer__col>summary{list-style:none;cursor:default}.rr-footer__col>summary::-webkit-details-marker{display:none}
.rr-footer a{color:var(--ink-2);text-decoration:none}.rr-footer a:hover{color:var(--gold-2);text-decoration:underline;text-underline-offset:3px}
.rr-footer__wire{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;margin-top:8px}
.rr-footer__legal{margin-top:32px;padding-top:16px;border-top:1px solid var(--edge);display:grid;gap:8px;font-size:12px;line-height:18px;color:var(--dim)}
.rr-footer__line{color:var(--ink-2)}.rr-footer__legal .micro{color:var(--dim)}
/* phone: each group is one 48px row that opens to two columns of 40px links (nav.js keeps them shut here and
   open on desktop). Was a single column of 28 links: 1,538px, 1.8 screens, on every page. */
@media(max-width:760px){.rr-footer{margin-top:32px;padding-block:20px}.rr-footer__cols{grid-template-columns:1fr;gap:0;border-bottom:1px solid var(--edge)}.rr-footer__col{border-top:1px solid var(--edge)}.rr-footer__col>summary.kicker{display:flex;align-items:center;justify-content:space-between;min-height:48px;margin:0;cursor:pointer}.rr-footer__col>summary::after{content:"+";font:400 20px/1 var(--sans);letter-spacing:0;color:var(--ink-2)}.rr-footer__col[open]>summary::after{content:"\2212"}.rr-footer__col ul{display:grid;grid-template-columns:1fr 1fr;gap:0 16px;padding-bottom:8px}.rr-footer__col li{margin:0}.rr-footer__col a{display:block;min-height:40px;padding-block:10px}.rr-footer__legal{margin-top:16px;padding-top:0;border-top:0}.rr-footer__line a{display:inline-block;padding-block:13px;margin-block:-13px}}
@media(max-width:480px){.rr-footer__cols{grid-template-columns:1fr}.rr-footer__wire{grid-template-columns:1fr}}

/* 9. GRADES (F29: ONE scale, read from [data-grade] — seal, pill, scale strip, distribution bar, map legend, ridge-viz.js all consume these) */
[data-grade="Aaa"]{--gf:var(--g-aaa);--gt:var(--g-aaa-t);--gi:var(--g-aaa-i)}[data-grade="Aa"]{--gf:var(--g-aa);--gt:var(--g-aa-t);--gi:var(--g-aa-i)}
[data-grade="A"]{--gf:var(--g-a);--gt:var(--g-a-t);--gi:var(--g-a-i)}[data-grade="Baa"]{--gf:var(--g-baa);--gt:var(--g-baa-t);--gi:var(--g-baa-i)}
[data-grade="Ba"]{--gf:var(--g-ba);--gt:var(--g-ba-t);--gi:var(--g-ba-i)}[data-grade="B"]{--gf:var(--g-b);--gt:var(--g-b-t);--gi:var(--g-b-i)}
[data-grade="Caa"]{--gf:var(--g-caa);--gt:var(--g-caa-t);--gi:var(--g-caa-i)}[data-grade="NR"]{--gf:var(--g-nr);--gt:var(--g-nr-t);--gi:var(--g-nr-i)}
.dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--gf,var(--edge-2));flex:0 0 auto;vertical-align:middle}
/* seal: Fraunces 700 letter on a white disc with a 3px grade ring; the letter is coloured only at ≥28px (--md); --sm sets ink + a 3px left rule */
.seal{--s:56px;--fs:28px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:var(--s);height:var(--s);border:3px solid var(--gf,var(--edge-2));border-radius:50%;background:var(--panel);color:var(--gf,var(--ink));font:700 var(--fs)/1 var(--serif);font-variation-settings:'opsz' 144;letter-spacing:-.02em;text-decoration:none}
.seal--xl{--s:128px;--fs:64px;border-width:4px}.seal--lg{--s:88px;--fs:44px}.seal--md{--s:56px;--fs:28px}
.seal--sm{--s:28px;--fs:16px;width:auto;border:0;border-left:3px solid var(--gf,var(--edge-2));border-radius:0;background:none;color:var(--ink);padding:0 2px 0 7px;justify-content:flex-start}
.seal-block{display:inline-flex;flex-direction:column;align-items:center;gap:6px;text-align:center}
@media(max-width:480px){.seal--xl{--s:88px;--fs:44px;border-width:3px}.seal--lg{--s:64px;--fs:32px}}
/* scale: the 7-cell Aaa→Caa strip with the 'here' marker (lifted from report.html into the system) */
.scale{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;padding-top:16px;list-style:none;margin:0}
.scale__cell{position:relative;height:32px;display:flex;align-items:center;justify-content:center;background:var(--gt);color:var(--gi);border-top:4px solid var(--gf);border-radius:0 0 3px 3px;font:500 11px/1 var(--mono);letter-spacing:.06em}
.scale__cell.is-here{box-shadow:inset 0 0 0 2px var(--gf);font-weight:600}
.scale__cell.is-here::before{content:"▲ here";position:absolute;left:50%;top:-18px;transform:translateX(-50%);font:500 11px/13px var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2);white-space:nowrap}
.scale__cell.is-here[data-here]::before{content:attr(data-here)}
@media(max-width:480px){.scale{gap:3px}.scale__cell{height:30px;font-size:11px;letter-spacing:.02em}}
/* grade-pill: tint background + grade ink text + 1px border at 35% fill (same class in Pulse, search, hub, Wire, map popover, embed) */
.grade-pill{display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 8px;border-radius:999px;background:var(--gt,var(--panel-2));color:var(--gi,var(--ink));border:1px solid var(--gf,var(--edge-2));border-color:color-mix(in srgb,var(--gf,var(--edge-2)) 35%,transparent);font:600 12px/1 var(--sans);letter-spacing:.01em;white-space:nowrap;text-decoration:none;vertical-align:middle}
.grade-pill--dot::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--gf)}
/* printline: micro provenance row, 11px sans with tabular figures (mono took the homepage past the 15% monospace target) — every value from server tokens (F17) */
.printline{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px;margin-top:16px;padding-top:12px;border-top:1px solid var(--edge);font:400 11px/16px var(--sans);letter-spacing:.01em;font-variant-numeric:tabular-nums;color:var(--dim)}
.printline b{font-weight:500;color:var(--ink-2)}
.printline__copy{min-height:24px;padding:2px 8px;border:1px solid var(--edge-2);border-radius:var(--r-sm);background:var(--panel);font:500 11px/16px var(--mono);letter-spacing:.04em;color:var(--ink-2)}
.printline__copy:hover{border-color:var(--ink);color:var(--ink)}
@media(max-width:760px){.printline__copy{min-height:44px;padding:6px 12px}}

/* 10. TILES / KPI ROW (F18 one vocabulary per tile; F32 null metric = muted n/a, never a dash tile; 4-up → 2×2 → 1-col only with sparklines) */
.tile{background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-md);padding:16px 18px;display:flex;flex-direction:column;gap:4px;text-decoration:none;color:var(--ink)}
.tile__v{font:600 28px/32px var(--serif);font-variation-settings:'opsz' 72;letter-spacing:-.01em;color:var(--ink)}
.tile__l{font:500 11px/16px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--ink-2)}
.tile__s{font:400 13px/19px var(--sans);color:var(--dim)}
.tile__s a,.tile__s .btn--link{font-size:13px}
.tile--na .tile__v{font:400 15px/32px var(--sans);color:var(--dim)}
.tile .spark{margin-top:6px}
.kpi-row{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}.kpi-row--3{grid-template-columns:repeat(3,1fr)}.kpi-row--2{grid-template-columns:repeat(2,1fr)}
@media(max-width:760px){.kpi-row,.kpi-row--3{grid-template-columns:repeat(2,1fr);gap:12px}.tile{padding:14px 16px}}
@media(max-width:480px){.kpi-row--spark,.kpi-row--stack{grid-template-columns:1fr}}

/* 11. TABLES .tbl + .tscroll (F05: sticky first column, data-priority="3" hidden ≤760, .can-scroll = overflows
   (hint + tabindex), scroll-reactive edge fades in the .tshell overlay from nav.js; 36/44px rows) */
.tscroll{position:relative;overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-md)}
/* The swipe affordance is an OVERLAY painted in --panel inside a non-scrolling shell, never a mask on the
   scroll box: a mask dims whatever is under it, so at scrollLeft=max it washed out the trailing digits of the
   last column — the column the reader swiped across to read (measured on /pulse at 390: cells right-aligned at
   x=357 inside a ramp starting at x=316). nav.js toggles has-fade-l / has-fade-r from scroll position, so the
   right fade is gone once the end is reached and the left fade appears once the sticky first column is pinned. */
.tshell{position:relative;min-width:0}
.tshell__fade{position:absolute;top:1px;bottom:1px;width:36px;z-index:2;opacity:0;pointer-events:none;transition:opacity .12s linear}
.tshell__fade--r{right:1px;border-radius:0 var(--r-md) var(--r-md) 0;background:linear-gradient(to left,var(--fade-c,var(--panel)),transparent)}
.tshell.has-fade-r>.tshell__fade--r{opacity:1}
/* The LEFT edge gets no gradient: ≤760 the first column is sticky, so a mirror fade would wash out the
   pinned names exactly the way the old right-edge mask washed out the last column's digits (measured: the
   'J' of 'Jumeirah 2' and the 'Al' of 'Al Bada' went grey). The pinned column earns its depth from its own
   rule instead — a real drop shadow once the body has scrolled under it, drawn beside the text, never over. */
.tshell__fade--l{display:none}
.tscroll__hint{display:none;font:400 11px/16px var(--sans);color:var(--dim);padding:6px 2px 0}
/* LONG MOBILE PAGES — the row cap and the Top pill, both injected by nav.js (section 10b) so they reach every
   table on the site at once instead of the two pages that hand-rolled a 'Show all' button. Measured at 390
   before this rule: /ajman 21,282px of document for one 249-row table, /developers and /developer-track-records
   19,408px for 171 rows, /community 13,763px for 137 — ~54 phone screens on /ajman with no way back to the top.
   The cap is POSITIONAL CSS, not a class stamped on each row: developers.html and the /community hub re-render
   and re-sort their tbody client-side, and per-row classes would then hide whichever rows happened to be 26th
   onward BEFORE the sort. nth-child always hides the rows that are 26th onward NOW, so the visible 25 are
   always the top 25 of the current sort, with no bookkeeping and no flash. Print shows every row again (§21). */
.tmore{margin:12px 0 0}
.tmore .btn{width:100%}
.tscroll.is-capped tbody>tr:nth-child(n+26){display:none}
/* the same cap one screen deeper on a desktop, where 25 rows is a third of the fold and 171 is still a
   scroll with no end in sight: nth-child cannot read a variable, so the two caps are two classes and
   nav.js picks one by viewport. */
.tscroll.is-capped-50 tbody>tr:nth-child(n+51){display:none}
.rr-top{position:fixed;z-index:58;right:var(--gutter);bottom:calc(var(--tabbar-h) + var(--safe-b) + 12px);display:none;align-items:center;gap:6px;min-height:44px;padding:0 18px;border:1px solid var(--edge-2);border-radius:999px;background:var(--panel);color:var(--ink);font:600 13px/1 var(--sans);box-shadow:var(--shadow-2);cursor:pointer}
.rr-top:hover{border-color:var(--ink)}
@media(max-width:760px){.rr-top.is-on{display:inline-flex}}
.tbl{width:100%;border-collapse:collapse;font:400 13px/19px var(--sans);color:var(--ink)}
.tbl th{font:500 11px/16px var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--ink-2);text-align:left;vertical-align:bottom;background:var(--panel-2);padding:10px 12px;border-bottom:1px solid var(--edge-2);white-space:nowrap}
.tbl td{height:36px;padding:7px 12px;border-top:1px solid var(--edge);vertical-align:middle;white-space:nowrap}
.tbl tbody tr:first-child td{border-top:0}
.tbl th:first-child,.tbl td:first-child{white-space:normal;min-width:120px}.tbl td:first-child{font-weight:500}
.tbl .num,.tbl .n{text-align:right;font-variant-numeric:tabular-nums}
/* PROSE COLUMNS. `.tbl td{white-space:nowrap}` is right for a figure and wrong for a sentence: a nowrap
   sentence sets the table's scrollWidth to the longest paragraph, so on a phone the reader gets an ~86px
   window onto it and every line is cut mid-word (measured on /sla at 390: .tscroll 356 wide, table 470,
   the "What it does" column 200 of which 86 was ever visible). data-col="prose" is the one escape hatch —
   it wraps, and it asks for a readable measure instead of the longest line. It goes on the th AND every
   cell in that column (attribute selectors do not inherit down a column). At ≤760 the minimum is dropped
   so the column can shrink into the box; a table whose prose still will not fit there belongs in
   .tbl--stack, which stops scrolling altogether. (0,2,0) beats `.tbl td` at (0,1,1) wherever it sits. */
.tbl [data-col="prose"]{white-space:normal;overflow-wrap:break-word;min-width:22ch;max-width:48ch}
.tbl tbody tr:nth-child(even) td{background:var(--panel-2)}
.tbl tbody tr:hover td,.tbl tr.is-subject td{background:var(--gold-tint)}
.tbl a{color:var(--ink);text-decoration:none}.tbl a:hover{text-decoration:underline;text-decoration-color:var(--gold-2);text-underline-offset:3px}
.tbl th[aria-sort]{cursor:pointer}
.tbl th>.th-sort{display:inline-flex;align-items:center;gap:4px;margin:0;padding:0;border:0;background:none;font:inherit;color:inherit;letter-spacing:inherit;text-transform:inherit;text-align:inherit;cursor:pointer}.tbl th[aria-sort="ascending"]::after{content:" ↑"}.tbl th[aria-sort="descending"]::after{content:" ↓"}
.tbl .seal--sm{height:22px;font-size:14px}
@media(max-width:760px){
.tbl{min-width:0}.tbl td{height:44px;padding:9px 12px}
.tbl th:first-child,.tbl td:first-child{position:sticky;left:0;z-index:1;background:var(--panel);box-shadow:1px 0 0 var(--edge);min-width:0;max-width:46vw}
.tbl th:first-child{background:var(--panel-2)}.tbl tbody tr:nth-child(even) td:first-child{background:var(--panel-2)}
.tshell.has-fade-l .tbl th:first-child,.tshell.has-fade-l .tbl td:first-child{box-shadow:3px 0 6px -2px rgba(28,42,54,.22),1px 0 0 var(--edge)}
.tbl tbody tr:hover td:first-child,.tbl tr.is-subject td:first-child{background:var(--gold-tint)}
.tbl [data-priority="3"]{display:none}.tscroll__hint{display:block}.tbl td a{display:inline-block;padding-block:11px;margin-block:-11px}
.tbl [data-col="prose"]{min-width:0;max-width:none}
/* .tbl--stack: JS-rendered tables that must never scroll — each row becomes a card, cells labelled by data-l (F04) */
.tbl--stack,.tbl--stack tbody,.tbl--stack tr,.tbl--stack td{display:block;white-space:normal;height:auto;min-width:0;max-width:none;position:static;box-shadow:none}
.tbl--stack thead{display:none}.tbl--stack tr{padding:12px 14px;border-top:1px solid var(--edge)}.tbl--stack td{padding:2px 0;border:0;background:none!important}
.tbl--stack td[data-l]::before{content:attr(data-l) " ";font:500 11px/15px var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--dim)}
/* The sticky-first-column block above is (0,2,1) — `.tbl td:first-child` — and .tbl--stack's shorthand
   above is only (0,1,1), so without this every stacked table kept a 46vw cap on its first cell, a hairline
   shadow painted down the middle of each card and the zebra background behind the label. /sla and /pricing
   had each re-undone exactly that in their own <style>; it belongs here once, at matching specificity and
   later in the cascade. The first cell is the card's title, so it also takes the weight. */
.tbl--stack th:first-child,.tbl--stack td:first-child{position:static;box-shadow:none;max-width:none;min-width:0;background:none}
.tbl--stack td:first-child{font-weight:600;padding-bottom:6px}
.tbl--stack tbody tr:first-child{border-top:0}
/* data-priority="3" buys horizontal room, and a stacked card has none to buy: dropping the column there
   costs the reader a fact and saves nothing. (0,2,0) ties `.tbl [data-priority="3"]` and comes later. */
.tbl--stack [data-priority="3"]{display:block}
/* a stacked cell is a labelled line, never a centred or right-aligned one: `.center` on a comparison cell
   and `.num` on a reconciliation figure both scatter the values across the card once the columns they were
   aligned to are gone. `.tbl .num` and `.center` are (0,2,0) and (0,1,0), so (0,2,1) here settles both. */
.tbl--stack td,.tbl--stack td.num,.tbl--stack td.center{text-align:left}}

/* 12. ROWCARD (F04/F09: 'pill + name + ticket' on line 1, 'yield · type' on line 2 — the stacked fallback for shortlists) */
.rowlist{display:flex;flex-direction:column;gap:8px}
.rowcard{display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px;padding:10px 14px;background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-md);font:400 13px/19px var(--sans);color:var(--ink);text-decoration:none}
a.rowcard:hover{border-color:var(--edge-2);background:var(--panel-2)}
.rowcard>.grade-pill,.rowcard>.seal{flex:0 0 auto}
.rowcard__name{flex:1 1 0;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rowcard__v{margin-left:auto;font-variant-numeric:tabular-nums;white-space:nowrap}
.rowcard__s{flex-basis:100%;font-size:12px;line-height:16px;color:var(--dim)}

/* 13. CHIPS (F02: one pill grammar for registry answers, filters and suggestions; .chip-row wraps, --scroll peeks 24px, never clips) */
.chip{display:inline-flex;align-items:center;gap:6px;min-height:28px;padding:4px 10px;border:1px solid var(--edge);border-radius:999px;background:var(--panel-2);font:500 12px/16px var(--sans);color:var(--ink);text-decoration:none;white-space:nowrap}
a.chip:hover,button.chip:hover{border-color:var(--ink);color:var(--ink)}
.chip.is-on{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.chip.is-on .dim{color:var(--edge-2)}   /* --dim on ink measured 2.62:1 (axe, /wire); --edge-2 is 8:1 */
.chip-row{display:flex;flex-wrap:wrap;gap:8px}
@media(max-width:760px){a.chip,button.chip{min-height:44px}
.chip-row--scroll{flex-wrap:nowrap;overflow-x:auto;margin-inline:calc(-1*var(--gutter));padding:2px var(--gutter);scroll-padding-inline:var(--gutter);scrollbar-width:none}
.chip-row--scroll::-webkit-scrollbar{display:none}.chip-row--scroll>*{flex:0 0 auto}.chip-row--scroll::after{content:"";flex:0 0 calc(var(--gutter) - 8px)}}

/* 14. BUTTONS (F28: exactly three — .btn / .btn--ghost / .btn--link; .btn--gold is the one Recommended-plan fill; 44px on touch) */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:40px;padding:9px 22px;border:1px solid var(--ink);border-radius:var(--r-md);background:var(--ink);color:var(--paper);font:600 14px/20px var(--sans);text-decoration:none;white-space:nowrap;cursor:pointer;-webkit-appearance:none;appearance:none}
.btn:hover{background:var(--ink-2);border-color:var(--ink-2);color:var(--paper)}
.btn--ghost{background:transparent;border-color:var(--edge-2);color:var(--ink)}.btn--ghost:hover{background:var(--panel);border-color:var(--ink);color:var(--ink)}
.btn--gold{background:var(--gold-2);border-color:var(--gold-2);color:#fff}.btn--gold:hover{background:#66501A;border-color:#66501A;color:#fff}
.btn--link{min-height:0;padding:0;border:0;border-radius:0;background:none;color:var(--ink);text-decoration:underline;text-decoration-color:var(--gold-2);text-underline-offset:3px}.btn--link:hover{background:none;color:var(--gold-2)}
.btn--sm{min-height:32px;padding:5px 12px;font-size:13px}
.btn[disabled],.btn.is-disabled{background:var(--disabled);border-color:var(--disabled);color:#fff;pointer-events:none}
.cta-row{display:flex;flex-wrap:wrap;align-items:center;gap:12px}
/* 44 is the floor for EVERY control, not just .btn: the chips (the AED/USD toggle among them), the small and
   link buttons, the two masthead icon buttons and the band's verify link all measured 40 at 390 before this. */
@media(max-width:760px),(pointer:coarse){.btn:not(.btn--link){min-height:44px}.btn--sm{min-height:44px}.btn--link{min-height:44px}
.rr-masthead__ic{width:44px;height:44px}.rr-band__verify{padding-block:13px;margin-block:-13px}.rr-masthead__wm{min-height:44px}}
@media(max-width:480px){.cta-row{flex-direction:column;align-items:stretch}.cta-row .btn:not(.btn--link){width:100%}}

/* 15. CARDS, DOCUMENT, SECTIONS, ACTIONS, NOTICE (rating-document frame: letterhead, 2px gold rule, seal + standfirst, print line; no shadows on content) */
.card{background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-md);padding:24px}
.card--doc{border-color:var(--edge-2);border-radius:var(--r-lg);padding:32px}
.letterhead{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:flex-end;gap:8px 16px;padding-bottom:14px;margin-bottom:24px;border-bottom:2px solid var(--gold)}
.letterhead__brand{font:500 13px/18px var(--mono);letter-spacing:.3em;text-transform:uppercase;color:var(--ink)}
.letterhead__brand small{display:block;margin-top:4px;font-size:11px;letter-spacing:.12em;color:var(--ink-2)}
.letterhead__meta{font:400 11px/16px var(--mono);letter-spacing:.04em;color:var(--dim);text-align:right}
.rating-head{display:grid;grid-template-columns:auto minmax(0,1fr);gap:24px;align-items:center}
.standfirst{font:600 17px/24px var(--sans);margin-top:8px}.standfirst__s{font:400 13px/19px var(--sans);color:var(--ink-2);margin-top:4px}
.sec{margin-top:48px}.sec__head{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:8px 16px;margin-bottom:16px}
.sec__k{display:block;margin-bottom:4px}.sec h2{margin:0}
.sec details,.page details.fold{border-top:1px solid var(--edge);padding:12px 0}
.sec summary,.page details.fold summary{display:flex;justify-content:space-between;gap:12px;cursor:pointer;list-style:none;font:600 14px/20px var(--sans);color:var(--ink)}
.sec summary::-webkit-details-marker,.page details.fold summary::-webkit-details-marker{display:none}
.sec summary::after,.page details.fold summary::after{content:"+";color:var(--dim);font-weight:400}
.sec details[open]>summary::after,.page details.fold[open]>summary::after{content:"–"}
.actions{list-style:none;margin:0;padding:0;border-top:1px solid var(--edge)}
.actions__row{display:grid;grid-template-columns:auto auto minmax(0,1fr) auto auto;gap:6px 12px;align-items:center;padding:10px 0;border-bottom:1px solid var(--edge);font:400 13px/19px var(--sans);color:var(--ink);text-decoration:none}
a.actions__row:hover .actions__n{text-decoration:underline;text-decoration-color:var(--gold-2);text-underline-offset:3px}
.actions__d{font:400 12px/16px var(--sans);letter-spacing:0;font-variant-numeric:tabular-nums;color:var(--dim);white-space:nowrap}
.actions__n{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.actions__a{font-weight:500;white-space:nowrap}.actions__r{color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* .actions__go is an <a> on the rating documents (report.html:143, building.html) and a <span> everywhere else,
   so the ≤480 `display:none` was being beaten by a tap-target rule — but NOT, as first diagnosed, by §16's
   `.page main a:not(…)` on specificity. The rule that actually won is `.doc li a{display:inline-block;
   padding-block:10px}` in report.html:28 and building.html:27, and it wins because it is UNLAYERED: this whole
   file sits in @layer ridge precisely so a page's own <style> beats it regardless of order or specificity
   (F03/F30, see the file header). Measured with CSSOM at 390 and 480: that one rule is the only `display`
   declaration matching the element, and `.actions__row .actions__go{display:none}` at (0,2,0) still lost to its
   (0,1,2). No selector written in this file can win that, so the hide below is !important — which in a layered
   sheet is the documented way the layer asserts over an unlayered page rule, not a specificity escape hatch:
   important-in-layer outranks normal-unlayered by cascade order. §16 additionally stops matching .actions__go,
   which drops the 8px inline padding that pulled the arrow's ink to x=25 against x=33 for every sibling. */
.actions__go{color:var(--gold-2)}
.notice{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;padding:12px 16px;background:var(--panel-2);border:1px solid var(--edge);border-radius:var(--r-md);font:400 13px/19px var(--sans);color:var(--ink)}
.disclosure{margin-top:24px;padding:2px 0 2px 12px;border-left:3px solid var(--gold-2);font:400 12px/18px var(--sans);color:var(--ink-2)}
.calendar{display:flex;flex-wrap:wrap;gap:4px 16px;font:400 13px/19px var(--sans);color:var(--ink-2)}.calendar b{font-weight:500;color:var(--ink)}
.ink-band{background:var(--ink-panel);color:var(--paper)}
.ink-band h2,.ink-band h3{color:var(--paper)}.ink-band .kicker{color:var(--gold-light)}.ink-band p{color:var(--paper);opacity:.92}
.ink-band a:not(.btn){color:var(--paper);text-decoration-color:var(--gold-light);display:inline-block;padding-block:10px;margin-block:-10px}.ink-band .btn{background:var(--paper);border-color:var(--paper);color:var(--ink)}.ink-band .btn:hover{background:#fff;border-color:#fff;color:var(--ink)}
/* MEASURE INSIDE A RATING DOCUMENT. §16 caps prose at 68ch on .prose, but /community/* and /building/* are
   built from .container--doc and never carry .prose, so the one place the type has to be disciplined was the
   one place the measure was unmanaged. Measured at 1440 on /community/dubai-marina: p.lede 622px/58ch, then the
   two rationale <p> beneath it 834px/88ch, .body-s 834px/102ch — two column edges 212px apart in one section.
   ONE edge for the whole document column: 640px is 67ch at the 15px body and 60ch at the 17px lede, both inside
   the 58–68ch rule, and the lede no longer stops short of the paragraphs it introduces. Per-element `68ch` was
   tried first and is worse here: it resolves to 645px at 15px, 728px at the lede and 558px on .body-s, which is
   three edges instead of two. Tables, charts and their captions, the print row, the .notice banner and the
   .calendar/.actline metadata rows keep the full grid column, as the spec's 'tables may exceed it' requires.
   Inert ≤760, where the column is already 294–408px. */
.container--doc{--measure:640px}
.container--doc p:not(.printline):not(.calendar):not(.notice):not(.viz__sub):not(.viz__src){max-width:var(--measure)}
@media(max-width:760px){.card{padding:16px}.card--doc{padding:20px 16px}.letterhead__meta{text-align:left}.rating-head{gap:16px}.sec{margin-top:24px}.sec__head{margin-bottom:12px}.actions__row{padding:11px 0}.sec summary,.page details.fold summary{min-height:44px;align-items:center}}
@media(max-width:480px){.seal-block .seal--xl{--s:80px;--fs:40px}.standfirst{font-size:15px;line-height:22px}.actions__row{grid-template-columns:auto auto minmax(0,1fr)}.actions__a,.actions__r{grid-column:1/-1}.actions__a{margin-top:-4px}.actions__row .actions__go{display:none!important}}

/* 16. PROSE, FORMS, SEARCH, GATE, CODE, SKELETON, MAP BAND (F31 gate as a document; F20/F37 static map band; inputs ≥16px on phones) */
.prose{max-width:68ch}.prose p,.prose ul,.prose ol{margin:0 0 16px}.prose li{margin-bottom:6px}
.prose h2{margin:48px 0 16px}.prose h3{margin:32px 0 8px}.prose h2:first-child{margin-top:0}
/* a .sec already carries the 48px; without this the kicker keeps it and pushes its own h2 48px away */
.prose .sec>.sec__k{margin-bottom:6px}.prose .sec>.sec__k+h2{margin-top:0}
.prose blockquote{margin:0 0 16px;padding-left:16px;border-left:3px solid var(--gold-2);color:var(--ink-2)}
.prose code,.page :where(code){font:400 13px/1.4 var(--mono);background:var(--panel-2);padding:1px 5px;border-radius:4px}
.prose .tscroll{margin:0 0 16px}
.field{display:grid;gap:6px}.field label{font:500 13px/18px var(--sans);color:var(--ink-2)}
.input,.select,.textarea,.page :where(input:not([type=checkbox],[type=radio],[type=range],[type=submit],[type=button]),select,textarea){width:100%;max-width:100%;min-height:44px;padding:10px 12px;border:1px solid var(--edge-ctl);border-radius:var(--r-sm);background:var(--panel);color:var(--ink);font:400 15px/20px var(--sans)}
.textarea,.page :where(textarea){min-height:96px;resize:vertical}
.page :where(input,select,textarea)::placeholder{color:var(--dim)}
.form-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:end}
.search{position:relative}.search__in,.search .input{height:48px;padding-left:40px}
.search__ic{position:absolute;left:12px;top:14px;width:20px;height:20px;stroke:var(--dim);fill:none;stroke-width:1.8;pointer-events:none}
.ac-list{position:absolute;top:100%;left:0;right:0;z-index:40;margin:4px 0 0;padding:4px;list-style:none;max-height:320px;overflow:auto;background:var(--panel);border:1px solid var(--edge-2);border-radius:var(--r-md);box-shadow:var(--shadow-2)}
.ac-list li,.ac-list [role="option"]{display:flex;align-items:center;gap:10px;min-height:40px;padding:6px 10px;border-radius:var(--r-sm);font:400 14px/20px var(--sans);color:var(--ink);cursor:pointer}
.ac-list li:hover,.ac-list [aria-selected="true"]{background:var(--panel-2)}
.ac-list .grade-pill{margin-left:auto}
.gate{display:grid;gap:16px;padding:24px;background:var(--panel);border:1px solid var(--edge-2);border-radius:var(--r-lg)}
.gate__proof{filter:blur(5px);pointer-events:none;user-select:none;opacity:.8}
.gate__form{display:grid;grid-template-columns:1fr 1fr 1fr auto;gap:8px;align-items:end}
.code,.page :where(pre){position:relative;margin:0 0 16px;padding:14px 16px;background:var(--ink-panel);color:var(--paper);border-radius:var(--r-md);font:400 12px/18px var(--mono);overflow-x:auto;tab-size:2}
.code__copy{position:absolute;top:8px;right:8px;min-height:28px;padding:4px 10px;border:1px solid rgba(246,242,233,.35);border-radius:var(--r-sm);background:transparent;color:var(--paper);font:500 11px/16px var(--sans)}
.code__copy:hover{border-color:var(--paper)}
.skel{min-height:24px;border-radius:var(--r-md);background:linear-gradient(90deg,var(--panel-2) 25%,var(--gold-tint) 37%,var(--panel-2) 63%);background-size:400% 100%;animation:rr-shimmer 1.4s ease infinite}
.skel__l{font:400 13px/19px var(--sans);color:var(--dim);text-align:center;padding:16px}
@keyframes rr-shimmer{0%{background-position:100% 0}100%{background-position:0 0}}
.mapband{position:relative;display:block;overflow:hidden;aspect-ratio:12/5;background:var(--panel);border:1px solid var(--edge-2);border-radius:var(--r-lg);color:var(--ink);text-decoration:none}
.mapband svg,.mapband img{display:block;width:100%;height:100%;object-fit:cover}
.mapband__legend{position:absolute;top:12px;left:12px;display:flex;flex-wrap:wrap;gap:6px;max-width:calc(100% - 24px)}
.mapband__cap{position:absolute;left:12px;bottom:12px;max-width:60%;padding:6px 10px;background:rgba(255,255,255,.92);border-radius:var(--r-sm);font:400 12px/16px var(--sans);color:var(--ink-2)}
.mapband__cta{position:absolute;right:12px;bottom:12px}
@media(max-width:760px){.gate__form,.form-row{grid-template-columns:1fr}.gate{padding:16px}
.input,.select,.textarea,.page :where(input:not([type=checkbox],[type=radio],[type=range],[type=submit],[type=button]),select,textarea){font-size:16px}
.code,.page :where(pre){white-space:pre-wrap;word-break:break-word;padding-top:48px}.code__copy{min-height:44px}
.ac-list li,.ac-list [role="option"]{min-height:44px}
/* MAPBAND ≤760 (F20/F37): the spec layout — caption top-left, CTA bottom-right — exists so the choropleth
   stays visible. The rule this replaces stretched the caption across the full width AND the CTA across the
   full width, with the legend pinned immediately above it: 154 of 269px (57%) of the grade map was opaque
   furniture and the legend abutted the CTA with a 0px gap. The legend cannot share the bottom row with the
   CTA — its eight pills carry live counts ('Baa · 26') and measure ~515px all told — so it keeps the full
   width one clear row above the button (bottom 12 + 44 button + 8 gap = 64) instead. Reserving a fixed CTA
   width for it was tried and is worse at every width: the button is 170px on / and 233px on /community, so
   the reservation either overlapped the button or squeezed the pills into four rows. */
.mapband{aspect-ratio:4/3}
.mapband__cap{top:12px;bottom:auto;left:12px;right:auto;max-width:66%}
.mapband__legend{top:auto;bottom:64px;left:12px;right:auto;max-width:calc(100% - 24px)}
.mapband:not(:has(.mapband__cta)) .mapband__legend{bottom:12px}   /* the /report and /building locators have no button */
.mapband__cta{left:auto;right:12px;bottom:12px}
/* TAP TARGETS (F24): an inline prose link is 19px tall — every rebuilt page repeated this rule in its own
   <style> so that inline <a>, .calendar and .printline links measure ≥40×40 on a phone. One copy, here. */
.page main a:not(.btn):not(.chip):not(.grade-pill):not(.seal):not(.tile):not(.rowcard):not(.actions__row):not(.actions__go):not(.mapband){display:inline-block;min-width:40px;min-height:40px;padding:13px 8px;margin:-13px -8px}
.printline a{padding-block:15px;margin-block:-15px}
/* a sortable column header is a <button> (keyboard-reachable): it gets the same 40px floor, its padding
   cancelled by negative margins so the header row keeps its height */
.tbl th>.th-sort{min-width:40px;min-height:40px;padding-block:12px;margin-block:-12px}}
/* ≤480: a 4/3 band is only 269px tall at 390 — too shallow for three plates, so square it up (the finding's
   own fallback) so the choropleth keeps ≥180px of clear height, and tighten the caption, the pills and the
   button. A 66% caption is taller than a full-width one at this size, so here it spans the width instead —
   still anchored top-left. Measured on / at 390: clear map height 89px → 181px, legend/CTA gap 0px → 8px. */
@media(max-width:480px){.mapband{aspect-ratio:1/1}
.mapband__cap{right:12px;max-width:none;padding:5px 8px;font-size:11px;line-height:15px}
.mapband__legend{gap:4px}
.mapband__legend .grade-pill{height:20px;padding:0 6px;gap:4px;font-size:11px}
.mapband__cta .btn{padding-inline:12px;font-size:13px}}

/* 17. CHARTS (F36: SVG built at real pixel width, 11px fixed labels in --dim; F19 sparkline states; series --ink/--gold/--dim, gridlines --edge, base line --edge-2) */
.viz{position:relative;min-width:0}
.viz svg{display:block;width:100%;height:auto;overflow:visible}
.viz svg text{font-family:var(--sans);font-size:11px;fill:var(--dim)}
.viz__title{font:600 17px/24px var(--sans);margin:0 0 2px;color:var(--ink)}
.viz__sub{font:400 13px/19px var(--sans);color:var(--dim);margin:0 0 12px}
.viz__src{font:400 11px/16px var(--sans);color:var(--dim);margin:8px 0 0}
.viz__legend{display:flex;flex-wrap:wrap;gap:6px 16px;margin:0 0 8px;font:400 12px/16px var(--sans);color:var(--ink-2)}
.viz__legend i{display:inline-block;width:14px;height:0;border-top:2px solid var(--ink);vertical-align:middle;margin-right:6px}
.viz__legend i.gold{border-color:var(--gold)}.viz__legend i.dim{border-color:var(--dim);border-top-style:dashed}
.viz__plot{position:relative;touch-action:pan-y}
.viz__read{position:absolute;top:8px;z-index:5;pointer-events:none;padding:6px 9px;background:var(--panel);border:1px solid var(--edge-2);border-radius:var(--r-sm);box-shadow:var(--shadow-2);font:400 12px/17px var(--sans);color:var(--ink);white-space:nowrap;font-variant-numeric:tabular-nums}
.viz__read b{font-weight:600}.viz__read[hidden]{display:none}
.spark{display:block;line-height:0;min-width:0}.spark svg{display:block;max-width:100%}
.trend{display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px}.trend__spark{width:140px;height:44px;flex:0 0 auto}
.trend__v{font:600 15px/20px var(--sans)}.trend__l{font:400 12px/16px var(--sans);color:var(--dim)}.trend__na{font:400 13px/19px var(--sans);color:var(--dim)}
.gradebar{min-width:0}.gradebar__bar{display:flex;gap:2px;height:36px}
.gradebar__seg{position:relative;min-width:4px;display:flex;align-items:center;justify-content:center;padding:0;border:0;overflow:hidden;background:var(--gf);color:#fff;font:700 19px/1 var(--serif);font-variant-numeric:tabular-nums;transition:opacity .15s;cursor:pointer}
.gradebar__seg:first-child{border-radius:3px 0 0 3px}.gradebar__seg:last-child{border-radius:0 3px 3px 0}
.gradebar.has-filter .gradebar__seg:not(.is-on){opacity:.35}
.gradebar__labels{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:8px}
.gradebar__lab{display:inline-flex;align-items:center;gap:6px;min-height:24px;padding:0 2px;border:0;background:none;font:400 12px/16px var(--sans);color:var(--ink-2);font-variant-numeric:tabular-nums}
.gradebar__lab b{font:500 11px/16px var(--mono);letter-spacing:.06em;color:var(--gi)}
.gradebar__lab.is-on{color:var(--ink);box-shadow:inset 0 -2px 0 var(--gf)}
@media(max-width:760px){.gradebar__bar{height:40px}.gradebar__seg{font-size:19px}.gradebar__lab{min-height:44px}}

/* 18. LEGACY SCOPE — nav.js v19 adds .legacy to <body> on pages without .page; their old token names resolve to the system's */
body.legacy{--bg:var(--paper);--white:var(--ink);--ice:var(--ink-2);--ink2:var(--ink-2);--edge2:var(--edge-2);--panel2:var(--panel-2);--card:var(--panel);--green:var(--up);--red:var(--down);--amber:var(--warn)}

/* 19. MOTION */
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}.skel{animation:none}}
}

/* 20. FOCUS — unlayered and !important so it wins over any page rule: a 2px gold ring (≥3:1 on paper, white and ink) */
:is(a,button,input,select,textarea,summary,[tabindex],[role="button"]):focus-visible{outline:2px solid var(--gold)!important;outline-offset:2px!important;box-shadow:none}
:focus:not(:focus-visible){outline:none}

/* 20b. PHONE FOLDS (nav.js mfolds) — unlayered, like the focus ring: a folded section's hide must beat a page's own
   display rules (the methodology weights bar is display:flex in the page's <style>). `screen` because print is laid
   out at ~673px and must show every section. */
.btn.mfold-btn{display:none}
@media screen and (max-width:760px){.btn.mfold-btn{display:flex;align-items:center;justify-content:space-between;width:100%;margin-top:12px}
.mfold-btn::after{content:"+";font:400 20px/1 var(--sans);margin-left:12px}.mfold-btn[aria-expanded="true"]::after{content:"\2212"}
section.is-mfolded>*:not(.mfold-keep){display:none!important}}

/* 21. PRINT — the rating document as a paper document: no chrome, black on white. The running header, the
   footer and 'Page n of N' live in the page margins, written per document by report.html/building.html
   (@page margin boxes need literal strings: Chrome has no string-set). The old position:fixed header sat
   INSIDE the content box and overprinted body text on every page after the first.
   Chrome lays print out at the A4 content width (~673px), so every ≤760px rule applies on paper too:
   the undo list for those is marked 'tablet rule'. */
.print-only{display:none}
@media print{
@page{margin:16mm}
#rr-masthead,.rr-masthead,.rr-band-slot,.rr-band,.rr-tabbar,#rr-footer,.rr-footer,.rr-sheet,.rr-scrim,.viz__read,.btn,.cta-row,.printline__copy,.code__copy,.tshell__fade,.tscroll__hint,.no-print{display:none!important}
/* screen-only parts of a rating document: the embed code, a calculator with no result, an undrawn map */
#embed,.unitref form,.unitref:not(.has-result),#location:not(.is-drawn){display:none!important}
.print-only{display:revert!important}
html,body{background:#fff!important;color:#000!important;padding:0!important;font-size:11pt;line-height:1.45}
a{color:#000!important;text-decoration:none!important}
.container,.container--doc,.container--prose{max-width:none;padding:0}
.grid--7-5,.grid--8-4,.grid--9-3{grid-template-columns:1fr}
.card,.tile,.tscroll,.notice,.gate{background:#fff!important;border-color:#999!important;box-shadow:none!important;break-inside:avoid}
.card--doc{border:0!important;border-radius:0;padding:0!important}
.letterhead{border-bottom-color:#000}
.seal,.scale__cell,.grade-pill,.gradebar__seg,.dot,.ink-band{print-color-adjust:exact;-webkit-print-color-adjust:exact}
.tbl th,.tbl td,.printline,.micro,.kicker,.viz__sub,.viz__src{color:#000}
.tbl tbody tr:nth-child(even) td{background:#f2f2f2!important}
.viz svg text{fill:#000}
/* page flow: a heading, a kicker or a lead-in line never ends a page apart from what it introduces; a
   table of up to 12 rows stays whole, a longer one breaks between rows (its header row repeats). At run
   time every .tscroll sits in a .tshell wrapper, so both are named. */
h1,h2,h3,h4,.sec__head,.kicker,.label,summary{break-after:avoid}.sec{margin-top:24px}
p{orphans:3;widows:3}
/* a lead-in line is also unbreakable: otherwise Chrome keeps it with its table by splitting it across the
   page, orphans and widows notwithstanding (measured on the building Peers block) */
p:has(+ .tscroll),p:has(+ .tshell),p:has(+ .kpi-row),p:has(+ .chip-row),p:has(+ .viz),p:has(+ .mapband),p:has(+ ul),p:has(+ form){break-after:avoid;break-inside:avoid}
.viz{break-inside:avoid}   /* a chart's title, plot and source line print on one page */
.tscroll,.tshell{overflow:visible;break-inside:auto}
:is(.tscroll,.tshell):not(:has(tbody>tr:nth-child(13))){break-inside:avoid}
.tbl [data-priority="3"]{display:table-cell}   /* tablet rule: a printed table keeps every column */
.tbl th:first-child,.tbl td:first-child{position:static;box-shadow:none!important;max-width:none}   /* tablet rule: the sticky first column, its divider and its 46vw cap */
/* code: the dark panel is a background, and browsers drop backgrounds by default, leaving paper-coloured
   text on white paper. Ink on paper instead; the 48px copy-button gap is a tablet rule. */
.code,.page :where(pre){background:#fff!important;color:#000!important;border:1px solid #999;padding:10px 12px!important;break-inside:avoid}
/* the locator figure: full width at its drawn proportion (the 4:3 box is a tablet rule); legend and
   caption sit under the drawing, not over it, since their white panels are backgrounds and do not print */
.mapband{aspect-ratio:auto!important;overflow:visible;border-color:#999!important;break-inside:avoid}
.mapband svg{height:auto!important}
.mapband__legend,.mapband__cap{position:static!important;max-width:none!important;margin:0;padding:6px 10px 0;background:none!important}
.mapband__cap{display:block;padding-bottom:8px}
/* a reference link prints where it points: 'Methodology' alone means nothing on paper */
a.ref::after{content:" (ridgeratings.com" attr(href) ")"}
/* the mobile row cap is a reading affordance, not an edit: an attachable document prints every row. Same
   specificity as the cap rule and later in the file, so no !important is needed. */
.tscroll.is-capped tbody>tr:nth-child(n+26){display:table-row}
.tscroll.is-capped-50 tbody>tr:nth-child(n+51){display:table-row}
/* every disclosure prints EXPANDED: an attachable Rating Report that silently omits its own provenance,
   rating history and exact math is not the document it claims to be (measured: 9 details, 0 open). A closed
   <details> hides its body through the details-content pseudo-element, not through display:none on the
   children, so that is what has to be overridden; the +/– affordance means nothing on paper, so it goes. */
/* a fold's title cannot be held to its body by break-after (Chrome ignores it across the <details>
   boundary; measured), so a fold stays whole unless it holds a long table */
details{break-inside:auto}
details.fold:not(:has(tbody>tr:nth-child(13))){break-inside:avoid}
details::details-content{content-visibility:visible!important;block-size:auto!important;height:auto!important;overflow:visible!important}
details:not([open])>*:not(summary){content-visibility:visible!important}
.sec summary,.page details.fold summary{cursor:auto}
.sec summary::after,.page details.fold summary::after,.sec details[open]>summary::after,.page details.fold[open]>summary::after{content:""}
}

/* ═══ APPENDED BLOCK · pages agent · static grade-map band · keep at the END of the file ═══════════
   /grade-map.svg is 1200×760 (aspect 1.579). §16's shared .mapband is 12/5 (2.40) above 760, 4/3 ≤760
   and 1/1 ≤480, and it paints its child with object-fit:cover — so the static figure was cropped, not
   fitted: measured on /community at 1440, 34% of the map's height was discarded, with whole community
   polygons sliced flat along the band's bottom edge; 15% of its width at 760 and 37% at 390.
   Two different things share the .mapband class: the STATIC FIGURE band (homepage §6, and the
   /community hub header built in server.py::_community_index) which contains an <img class="mapband__img">,
   and the INTERACTIVE LOCATOR on /community/<slug> and /building/<c>/<slug>, which contains a Maps
   canvas in .mapband__map and no img at all. Only the first is retargeted — via :has(), already used
   in §16 — so the locator keeps the design system's band shape and nothing about /map changes (its
   fallback is .map-fb, a different component).
   The figure is matted, never cropped: object-fit:contain at every width, and above 760 the band takes
   the figure's own 1200/760 so there is no mat to see either. :has(>img.mapband__img) is (0,2,1) and
   outranks the plain .mapband aspect-ratio rules in §16, so the two narrow bands are restated here.
   These are the same rules home_spa.html carried page-locally; they live here now because the hub's
   markup is emitted by server.py and cannot carry a page-local style. */
.mapband:has(>img.mapband__img){aspect-ratio:1200/760}
.mapband>img.mapband__img{object-fit:contain;object-position:50% 50%}
@media(max-width:760px){.mapband:has(>img.mapband__img){aspect-ratio:4/3}}
@media(max-width:480px){.mapband:has(>img.mapband__img){aspect-ratio:1/1}}
