/* The Known Good — site stylesheet
 *
 * OWNED BY THE LEAD. Template writers consume this; they must not restyle it.
 *
 * Every rule down to the "DERIVED" banner is transcribed VERBATIM from the
 * locked mockups (`mockup/index.html` and `mockup/model-page.html`), which are
 * the visual contract. Where the two mockups differ, the superset is used and
 * the difference is noted inline. Nothing here was redesigned.
 *
 * Token values are DESIGN-LOCK.md §2. `--acw` and `--chipbg` are additional
 * tokens present in both mockups.
 */

/* ---------------------------------------------------------------- tokens */
/* Modal scrim. Needs separate values per theme: .46 of a near-black over the
   light page reads as a dim, but the same wash over the dark page (--bg #0B1A2E)
   is barely perceptible, so the drawer would float with nothing visually behind
   it. The dark value is darker and more opaque to buy back that separation. */
:root{--scrim:rgba(8,16,30,.46);--bg:#fff;--bg2:#f7f9fc;--panel:#fff;--panel2:#f1f4f9;--bd:#e4e7ec;--bds:#cfd5de;
 --tx:#0d1420;--tx2:#525e6d;--tx3:#8c96a3;--ac:#1082FE;--acw:#e9f2ff;--navy:#073170;
 --co:#d8492a;--vi:#6d5ce0;--gr:#159a5f;--am:#eab308;--chipbg:#fff}
html[data-theme="dark"]{--scrim:rgba(0,0,0,.66);--bg:#0B1A2E;--bg2:#0e2038;--panel:#132542;--panel2:#0f1d33;--bd:#20304a;--bds:#2c3d5a;
 --tx:#e8eef7;--tx2:#a1b1c7;--tx3:#6f8199;--ac:#3b8cf6;--acw:#132a4a;--navy:#8fb8f0;
 --co:#ff6a4d;--vi:#9085e9;--gr:#34d399;--am:#f5c518;--chipbg:#f2f5f9}

*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--tx);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,sans-serif;line-height:1.5;-webkit-font-smoothing:antialiased}
.wrap{max-width:1260px;margin:0 auto;padding:0 22px}

/* ---------------------------------------------------------------- header */
header{position:sticky;top:0;z-index:40;background:var(--bg);border-bottom:1px solid var(--bd)}
.hrow{display:flex;align-items:center;gap:14px;padding:9px 0}
.lk{display:flex;align-items:center;gap:9px;text-decoration:none}.lk img{height:27px;display:block}
.wm{font-family:"Avenir Next","Futura",-apple-system,sans-serif;font-size:16.5px;letter-spacing:-.015em;white-space:nowrap}
.wm .the{font-weight:400;color:var(--tx3)}.wm .kg{font-weight:600;color:var(--navy)}
nav.top{display:flex;gap:4px;margin-left:6px;background:var(--panel2);border-radius:22px;padding:4px}
nav.top a{color:var(--tx2);text-decoration:none;font-size:12.5px;padding:5px 11px;border-radius:18px}
nav.top a:hover,nav.top a.on{background:var(--panel);color:var(--tx);box-shadow:0 1px 2px rgba(0,0,0,.06)}
.seg{display:inline-flex;border:1px solid var(--bd);border-radius:20px;overflow:hidden}
.seg button{background:transparent;border:0;padding:6px 8px;cursor:pointer;color:var(--tx3);display:flex}
.seg button.on{background:var(--panel2);color:var(--tx)}.seg svg{width:14px;height:14px}

/* ---------------------------------------------------------------- primitives */
.pill{font-size:11px;color:var(--tx2);background:var(--panel2);border:1px solid var(--bd);border-radius:20px;padding:3px 10px}
.card{background:var(--panel);border:1px solid var(--bd);border-radius:12px;padding:14px 16px}
h1{font-size:36px;font-weight:600;margin:0 0 8px;letter-spacing:-.6px;line-height:1.12}
/* model-page.html uses a smaller H1; carried on a page class so one stylesheet
   serves both mockups without changing either value. */
.page-model h1{font-size:31px;margin:8px 0 12px;letter-spacing:-.5px;line-height:1.15}
.lede{font-size:16px;color:var(--tx2);max-width:640px;margin:0 0 18px}
.btn{font-size:13px;border-radius:8px;padding:9px 16px;text-decoration:none;display:inline-block}
.btn-p{background:var(--ac);color:#fff}.btn-g{border:1px solid var(--bds);color:var(--tx)}
/* The mockup's Subscribe control is an <a>, which cannot submit a form. A real
   <button> needs these three to render identically. Same box, same type. */
button.btn{border:0;cursor:pointer;font-family:inherit;line-height:normal}
/* Links inside data tables. The mockup only ever styles links inline; this is
   the same --ac treatment, hoisted so templates stop repeating it. */
td a{color:var(--ac);text-decoration:none}
td a:hover{text-decoration:underline}

/* ---------------------------------------------------------------- hero announcements */
.ann{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:18px 0 4px}
.ann a{border:1px solid var(--bd);border-radius:12px;padding:13px 15px;text-decoration:none;color:inherit;background:var(--panel)}
.ann a:hover{border-color:var(--ac)}
.ann .k{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--ac);font-weight:600}
.ann .t{font-size:14.5px;font-weight:600;margin:3px 0 2px}
.ann .d{font-size:11.5px;color:var(--tx3);line-height:1.45}

/* ---------------------------------------------------------------- chart cards */
.hl-t{font-size:13px;font-weight:600;color:var(--tx2);padding-bottom:7px;border-bottom:1px solid var(--bd);margin:32px 0 14px}
.g3{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.chartbox{padding:14px 14px 6px}
.ctitle{font-size:16px;font-weight:600;display:flex;align-items:center;gap:8px;margin:0 0 3px}
.sq{width:11px;height:11px;border-radius:3px;display:inline-block;flex-shrink:0}
.csub{font-size:11px;color:var(--tx3);margin:0 0 8px}

/* ---------------------------------------------------------------- bars */
.bars{display:flex;align-items:flex-end;gap:4px;height:150px;border-bottom:1px solid var(--bd);position:relative;padding-top:6px}
.bars .gl{position:absolute;left:0;right:0;border-top:1px dashed var(--bd);opacity:.65}
/* Degenerate series: the container is KEPT so a tab switch can re-enter it (the
   JS re-queries .bars and bails if it is gone), but it must not keep the fixed
   height, flex layout or baseline rule of a real chart. */
.bars.flat{height:auto!important;display:block;border-bottom:0;padding-top:0}
/* height:88%, not 100%. The top 12% of every plot is a reserved headroom band
   that no bar and no value label may enter, so the chart can never paint into
   whatever sits above it. Measured before: the highest-painting element in a
   chart was .bval.out, landing +2.0px behind .ctrl, 0.0px behind .csub and
   -6.0px behind .legend (the homepage Openness card, a real overlap). With the
   band it lands 31-39px clear on all three. .bars keeps align-items:flex-end,
   so the bars still sit on the baseline and only the empty top moves.
   The gridlines stay at 25/50/75% of PLOT height: DESIGN-LOCK §4 states they
   are fractions of plot height, not value ticks, decorative, and must not be
   recomputed when the scale changes. Re-basing them onto the bar area would
   make them value-bearing, which §4 calls a different design, not a bug fix. */
.bcol{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;height:88%;position:relative;min-width:0;container-type:inline-size}
/* .bcol is position:relative, so each column paints as a unit in tree order
   (CSS 2.1 E.2 step 8): column i+1's BAR paints on top of column i's label
   wherever the label overflows into it. Measured on the first build of this
   change: 4,442 of 125,634 drawn labels were partly covered, worst case 5.5px
   of a 28px label. Raising the column that still owns a label fixes it without
   touching colour, which is fully allocated to the creator. Unsupported :has()
   degrades to the pre-existing behaviour rather than to something worse. */
.bcol:has(.bval.keep){z-index:1}
/* §4's width rule, the half CSS must own (§10, 27 Jul, third entry).
   The bar is min(column width, 26px). A label wider than the 26px CAP can never
   fit and is marked .out when the page is rendered -- that half is decided in
   build.py and charts.js. But below a 26px column the bar IS the column, and
   whether a given label fits then depends on a width no build step knows. The
   container query answers it at the real rendered width, at every viewport and
   through a resize, with no JavaScript.
   It over-triggers slightly: a short label in a 20px column would have fitted.
   That direction is free -- the value moves above its bar in --tx, which §4
   already specifies -- while the other direction is white text on a light card.
   Declarations are .bval.out's, repeated rather than shared, because a class
   cannot be added by a container query. */
@container (width < 26px){.bars .bval{color:var(--tx);position:absolute;top:-14px}}
/* [hidden] is a UA rule and an author `display:flex` beats it, so the count
   selector's hidden columns need this explicitly. Both rows must hide the same
   indices or every label slides off the bar it names. */
.bcol[hidden],.acol[hidden]{display:none}
/* The count selector hides with [hidden]; the page filter hides with a class.
   A column is visible only when NEITHER applies. */
.bcol.filtered-out,.acol.filtered-out{display:none}
/* position:relative is load-bearing. .bval.out is position:absolute with
   top:-14px, and its containing block is the nearest POSITIONED ancestor. .bar
   never declared position, so that ancestor was .bcol -- which spans the whole
   plot. top:-14px was therefore measured from the PLOT top, a constant, and
   every out-of-bar label in a chart landed on the same y no matter how tall its
   bar was: on a model page's Price card, 30 labels stacked in one row at the top
   of a plot whose bars were all at the 5% floor. DESIGN-LOCK §4 says the value
   "moves above IT", meaning the bar. This is what makes that true. */
.bar{width:100%;max-width:26px;border-radius:3px 3px 0 0;display:flex;justify-content:center;padding-top:5px;position:relative}
.bar.me{outline:2px solid var(--tx);outline-offset:1px}
/* Bars outside the ranked run — DESIGN-LOCK §4. Shape and text only, never
   colour: colour is fully allocated to creator identity.
   .pingap is align-self:flex-end + height:88%, matching .bcol. With
   align-self:stretch it spanned the full flex line while every column beside
   it is 88% of it, so the rule stood ~17px proud into the headroom band. */
.pingap{flex:0 0 1px;align-self:flex-end;height:88%;border-left:1px dashed var(--bds);margin:0 8px}
.prank{position:absolute;top:3px;right:50%;transform:rotate(-58deg) translateY(11px);transform-origin:100% 0;white-space:nowrap;font-size:8px;line-height:1.15;color:var(--tx3);text-align:right}
/* Clamped at 100%: the true value is off the ranked run's scale. The dashed cap
   marks the cut; .prank states it in words, which cannot be misread. */
.bar.over{border-top:2px dashed var(--tx)}
.bval{font-size:10px;font-weight:600;color:#fff}.bval.out{color:var(--tx);position:absolute;top:-14px}
/* Value-label thinning (D2). A COMPUTED PROPERTY, never a list of charts: a
   label may be drawn only where its column is wide enough to hold it.
       thin when   pitch < W + G          pitch = .bcol width + .bars gap (4px)
       i.e. when   .bcol width < W + G - 4
   .bcol is the query container, so the browser supplies the left-hand side at
   the chart's REAL rendered width -- at 1920, at 375, and continuously during a
   resize -- with no JavaScript and no listener. A build-time allowlist would be
   correct at one width and silently wrong at every other.
   W is the one term CSS cannot measure. build.py derives it per chart from that
   chart's OWN label strings (lw_bucket()) and emits .lwNN on .bars. Its advance
   table runs deliberately WIDE, so an error costs one label rather than letting
   two collide. G = 3px. Threshold below is therefore NN + 3 - 4 = NN - 1.
   A browser without @container support matches none of these and shows every
   label, which is the behaviour that shipped before this change.

   The same rungs also anchor the FIRST and LAST visible column's label to the
   inner edge. .bval is a flex item of .bar{justify-content:center}, so it is
   centred on its bar; at an extreme column its centre is only colw/2 from the
   container edge and it overhangs by (W - colw)/2, which .cscroll clips. A LEFT
   overhang sits at negative x and is not even reachable by scrolling. Measured
   on /models/anthropic-claude-opus-4-1/: '3,180' 9.5px past the left edge,
   '$30.00' 12.5px past the right. Section charts, at 69-75px columns, overhang
   by nothing -- which is why this rides the same width condition rather than a
   rule of its own: colw < W is the overhang condition, colw < W-1 the thinning
   one, and they coincide to within a pixel. */
@container (width < 5px){.bars.lw6 .bval:not(.keep){display:none}.bars.lw6 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw6 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 7px){.bars.lw8 .bval:not(.keep){display:none}.bars.lw8 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw8 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 9px){.bars.lw10 .bval:not(.keep){display:none}.bars.lw10 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw10 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 11px){.bars.lw12 .bval:not(.keep){display:none}.bars.lw12 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw12 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 13px){.bars.lw14 .bval:not(.keep){display:none}.bars.lw14 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw14 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 15px){.bars.lw16 .bval:not(.keep){display:none}.bars.lw16 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw16 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 17px){.bars.lw18 .bval:not(.keep){display:none}.bars.lw18 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw18 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 19px){.bars.lw20 .bval:not(.keep){display:none}.bars.lw20 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw20 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 21px){.bars.lw22 .bval:not(.keep){display:none}.bars.lw22 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw22 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 23px){.bars.lw24 .bval:not(.keep){display:none}.bars.lw24 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw24 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 25px){.bars.lw26 .bval:not(.keep){display:none}.bars.lw26 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw26 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 27px){.bars.lw28 .bval:not(.keep){display:none}.bars.lw28 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw28 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 29px){.bars.lw30 .bval:not(.keep){display:none}.bars.lw30 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw30 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 31px){.bars.lw32 .bval:not(.keep){display:none}.bars.lw32 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw32 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 33px){.bars.lw34 .bval:not(.keep){display:none}.bars.lw34 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw34 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 35px){.bars.lw36 .bval:not(.keep){display:none}.bars.lw36 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw36 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 37px){.bars.lw38 .bval:not(.keep){display:none}.bars.lw38 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw38 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 39px){.bars.lw40 .bval:not(.keep){display:none}.bars.lw40 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw40 .bcol.edge-r .bar{justify-content:flex-end}}
@container (width < 41px){.bars.lw42 .bval:not(.keep){display:none}.bars.lw42 .bcol.edge-l .bar{justify-content:flex-start}.bars.lw42 .bcol.edge-r .bar{justify-content:flex-end}}
.axis{display:flex;gap:4px;padding-top:7px}
.acol{flex:1;display:flex;flex-direction:column;align-items:center;min-width:0}
.alogo{width:18px;height:18px;border-radius:4px;background:var(--chipbg);border:1px solid var(--bd);display:flex;align-items:center;justify-content:center;padding:2px;text-decoration:none;font-size:8px;font-weight:700;color:#5a6675}
.alogo img{width:100%;height:100%;object-fit:contain}
.bulb{font-size:9px;color:var(--tx3);height:11px;line-height:11px}
.lblbox{height:84px;position:relative;width:100%}
.lbl{position:absolute;top:3px;right:50%;transform:rotate(-58deg);transform-origin:100% 0;white-space:nowrap;font-size:8.5px;line-height:1.15;color:var(--tx2);text-align:right;text-decoration:none}
.lbl.me{color:var(--tx);font-weight:700}.lbl:hover{color:var(--ac);text-decoration:underline}

/* ---------------------------------------------------------------- promo row */
.promo{display:grid;grid-template-columns:1fr 1fr 1fr 1.5fr;gap:14px;margin:22px 0 8px}
.pcard{background:var(--panel);border:1px solid var(--bd);border-radius:12px;padding:16px;display:flex;flex-direction:column;min-height:180px;text-decoration:none;color:inherit;position:relative}
.pcard:hover{border-color:var(--ac)}
.pc-h{font-size:19px;font-weight:500;line-height:1.25;letter-spacing:-.2px;padding-right:36px}
.pc-d{font-size:11.5px;color:var(--tx3);margin-top:auto;line-height:1.45}
.arrow{position:absolute;top:15px;right:15px;width:26px;height:26px;border-radius:7px;background:var(--ac);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px}
.chg{background:var(--bg2);border:1px solid var(--bd);border-radius:12px;padding:13px 15px;max-height:180px;overflow:auto}
.chg-i{padding:6px 0 6px 12px;border-left:2px solid var(--bd);margin-left:3px}
.chg-i .m{font-size:9.5px;color:var(--tx3)}
.chg-i .n{font-size:12px;display:flex;align-items:center;gap:6px}
.chg-i .n img{width:13px;height:13px;object-fit:contain}

/* ---------------------------------------------------------------- detail layout
   The border-top here IS the horizontal rule of DESIGN-LOCK §3 item 5. The left
   nav exists only inside this grid and must never appear above it. */
.layout{display:grid;grid-template-columns:212px 1fr;gap:32px;padding:26px 0 0;border-top:1px solid var(--bd);margin-top:26px}
.snav{position:sticky;top:60px;align-self:start;max-height:calc(100vh - 80px);overflow:auto;padding-right:6px}
.nv{display:flex;gap:9px;align-items:flex-start;font-size:11.5px;color:var(--tx3);text-decoration:none;padding:5px 4px;border-radius:6px;line-height:1.32}
.nv .d{width:8px;height:8px;border-radius:2px;background:var(--bds);flex-shrink:0;margin-top:4px}
.nv:hover{color:var(--tx2)}
.nv.on{color:var(--tx);font-weight:600}.nv.on .d{background:var(--tx)}
.sec{scroll-margin-top:70px;margin-bottom:44px}
.sech{font-size:22px;font-weight:600;margin:0 0 4px;display:flex;align-items:center;gap:10px;letter-spacing:-.3px}
.sub{font-size:13px;color:var(--tx2);margin:0 0 14px}

/* ---------------------------------------------------------------- tabs + controls */
.tabs{display:flex;gap:4px;background:var(--panel2);border-radius:9px;padding:4px;margin-bottom:12px;flex-wrap:wrap}
.tab{font-size:12px;padding:6px 13px;border-radius:6px;color:var(--tx2);cursor:pointer}
.tab.on{background:var(--panel);color:var(--tx);font-weight:600;box-shadow:0 1px 2px rgba(0,0,0,.07)}
.ctrl{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:2px 0 10px}
.sel{font-size:11.5px;border:1px solid var(--bds);border-radius:7px;padding:5px 11px;color:var(--tx2);background:var(--panel);display:flex;align-items:center;gap:7px}
.ico{width:27px;height:27px;border:1px solid var(--bd);border-radius:7px;display:flex;align-items:center;justify-content:center;color:var(--tx3);font-size:12px}
.addm{font-size:11.5px;color:var(--tx2);display:flex;align-items:center;gap:6px}
.addm .p{width:19px;height:19px;border-radius:50%;border:1px solid var(--bds);display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--tx3)}
/* Phase 5 -- the chart control row is interactive. cursor:pointer is scoped to
   the INTERACTIVE forms on purpose: `.sel` is also used as a static
   filter-result count on five index pages (evaluations, providers, changelog,
   comparisons, evaluation), and a bare `.sel{cursor:pointer}` would advertise
   interactivity on text that has none -- the inverse of the inert control this
   work removes. A <button> does not inherit font or line-height from its
   parent, so both are restored or the row reflows. */
button.sel,button.ico,button.addm{font-family:inherit;font-size:inherit;line-height:normal;margin:0}
button.addm{background:none;border:0;padding:0;font-size:11.5px}
button.sel,button.ico,button.addm,a.ico{cursor:pointer}
/* The table toggle carries visible text (DESIGN-LOCK §4), so it escapes the
   base .ico 27x27 box. Present in both mockups; this is its stylesheet twin. */
.ico.wide{width:auto;padding:0 9px;gap:6px;color:var(--tx2);font-size:11.5px}
a.ico{text-decoration:none}
/* Dropdown primitive shared by the count selector and the pin picker. The card
   is the anchor: .cscroll must not gain position or z-index (DESIGN-LOCK §4 /
   the browser-tested note in the chart-controls brief), and .ctrl sits beside
   it, so the menu hangs off .chartbox which already contains both. */
.chartbox{position:relative}
.kgmenu{position:absolute;top:0;left:0;z-index:30;min-width:150px;background:var(--panel);border:1px solid var(--bds);border-radius:9px;padding:4px;box-shadow:0 6px 20px rgba(0,0,0,.13);font-size:11.5px;color:var(--tx2)}
.kgmenu button{display:flex;align-items:center;gap:8px;width:100%;text-align:left;font-family:inherit;font-size:11.5px;line-height:1.4;padding:6px 9px;border:0;border-radius:6px;background:none;color:var(--tx2);cursor:pointer}
.kgmenu button:hover{background:var(--panel2);color:var(--tx)}
.kgmenu button[aria-selected="true"]{color:var(--tx);font-weight:600}
.kgmenu button:focus-visible{outline:2px solid var(--ac);outline-offset:-2px}
button.sel:focus-visible,button.ico:focus-visible,button.addm:focus-visible,a.ico:focus-visible{outline:2px solid var(--ac);outline-offset:2px}
.legend{display:flex;gap:14px;font-size:11px;color:var(--tx2);margin:8px 0 2px;flex-wrap:wrap}
.wmk{font-size:10px;color:var(--tx3);text-align:right;padding:4px 2px 0}
.mnote{background:var(--bg2);border:1px solid var(--bd);border-radius:10px;padding:12px 14px;margin-top:12px;font-size:11.5px;color:var(--tx2);line-height:1.55}
.mnote b{color:var(--tx)}

/* ---------------------------------------------------------------- trend chart */
.tlegend{display:flex;flex-wrap:wrap;gap:5px 15px;margin:8px 0 12px}
.tl{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--tx);cursor:pointer;user-select:none}
.tl .dot{width:9px;height:9px;border-radius:50%;flex-shrink:0}
.tl:hover{color:var(--ac)}
.tl.off{opacity:.3}.tl.off .dot{background:var(--tx3)!important}
.tl.hot{color:var(--ac);font-weight:600}
#TREND{position:relative}
#TREND .ser{transition:opacity .12s}
#TREND svg.dim .ser{opacity:.10}
#TREND svg.dim .ser.hot{opacity:1}
#TREND .ser.hot path.vis{stroke-width:2.6}
#TREND .hit{cursor:pointer}
.ttip{position:absolute;pointer-events:none;background:var(--panel);border:1px solid var(--bds);border-radius:9px;
 padding:9px 12px;font-size:11.5px;box-shadow:0 6px 20px rgba(0,0,0,.16);opacity:0;transition:opacity .1s;z-index:6;white-space:nowrap}
.ttip .dt{color:var(--tx3);font-size:10.5px}
.ttip .md{font-weight:600;margin:3px 0 5px;font-size:12.5px}
.ttip .cr{display:flex;align-items:center;gap:7px;color:var(--tx2)}
.ttip .cr b{margin-left:auto;color:var(--tx);padding-left:18px}

/* ---------------------------------------------------------------- field notes strip
   DESIGN-LOCK §7.10: must stop animating under prefers-reduced-motion and fall
   back to manual scroll. */
.strip{overflow:hidden;position:relative;padding:2px 0 6px}
.strip:before,.strip:after{content:"";position:absolute;top:0;bottom:0;width:60px;z-index:2;pointer-events:none}
.strip:before{left:0;background:linear-gradient(90deg,var(--bg),transparent)}
.strip:after{right:0;background:linear-gradient(270deg,var(--bg),transparent)}
.track{display:flex;gap:14px;width:max-content;animation:sc 52s linear infinite}
.strip:hover .track{animation-play-state:paused}
@keyframes sc{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media(prefers-reduced-motion:reduce){.track{animation:none}.strip{overflow-x:auto}}
.bcard{width:252px;flex-shrink:0;background:var(--panel);border:1px solid var(--bd);border-radius:12px;overflow:hidden;text-decoration:none;color:inherit}
.bcard:hover{border-color:var(--ac)}
.bcard .th{height:104px;background:linear-gradient(135deg,var(--navy),var(--ac))}
.bcard .bd{padding:11px 13px}
.bcard h4{font-size:13px;font-weight:600;margin:0 0 5px;line-height:1.35}
.bcard span{font-size:10.5px;color:var(--tx3)}

/* ---------------------------------------------------------------- model page */
.crumb{display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--tx2);padding-top:24px;flex-wrap:wrap}
.biglogo{width:34px;height:34px;border-radius:8px;background:var(--chipbg);border:1px solid var(--bd);display:flex;align-items:center;justify-content:center;padding:5px}
.biglogo img{width:100%;height:100%;object-fit:contain}
/* Lettered fallback inside the large chip, matching .alogo's treatment. */
.biglogo span{font-size:12px;font-weight:700;color:#5a6675}
.sumgrid{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin:20px 0}
/* Was an inline style on two templates, which no media query could override.
   Declared here so the 700px rule can actually reach it. */
.split{display:grid;grid-template-columns:1.55fr 1fr;gap:14px}
.sc{background:var(--panel);border:1px solid var(--bd);border-radius:12px;padding:13px 14px}
.sc-h{font-size:12.5px;font-weight:600;color:var(--tx2);margin-bottom:7px}
.rank{font-size:10.5px;color:var(--tx3);background:var(--panel2);border-radius:12px;padding:2px 8px;display:inline-block;margin-bottom:6px}
.sc-v{font-size:26px;font-weight:600;letter-spacing:-.5px;line-height:1.08}
.sc-u{font-size:10.5px;color:var(--tx3);line-height:1.35;margin-top:3px}
.units{display:flex;gap:3px;margin-top:9px}
.u{height:4px;flex:1;border-radius:2px;background:var(--panel2)}.u.f{background:var(--ac)}
.prose{font-size:13.5px;color:var(--tx2);line-height:1.65;margin:6px 0 0}
.prose b{color:var(--tx);font-weight:600}
.mrow{display:flex;align-items:center;gap:8px;margin:9px 0;font-size:11.5px;color:var(--tx2)}
.trk{flex:1;height:8px;border-radius:4px;background:var(--panel2);position:relative}

/* ---------------------------------------------------------------- tables */
table{width:100%;border-collapse:collapse}
th{font-size:11px;font-weight:600;color:var(--tx3);text-align:left;padding:8px;border-bottom:1px solid var(--bd)}
td{padding:9px 8px;border-bottom:1px solid var(--bd);font-size:12.5px}
td.r,th.r{text-align:right}

/* ---------------------------------------------------------------- footer */
footer{display:flex;flex-wrap:wrap;gap:26px;font-size:12px;color:var(--tx2);padding:20px 0 46px;border-top:1px solid var(--bd);margin-top:24px}
footer a{color:var(--tx2);text-decoration:none}
footer a:hover{color:var(--ac)}

/* ---------------------------------------------------------------- responsive */
@media(max-width:1000px){
 .layout{grid-template-columns:1fr}.snav{display:none}
 .g3,.promo,.ann{grid-template-columns:1fr}
 .sumgrid{grid-template-columns:1fr 1fr}
}

/* ======================================================================== *
 * DERIVED — the mockups do not draw these pages (leaderboard, models index,
 * providers, evaluations, arenas, trends, data, static pages). The rules below
 * add only LAYOUT for them and are built strictly from the primitives above:
 * no new colours, no new type scale, no component library. Anything visual
 * reuses .card / .pill / table / .sel / .tabs.
 * ======================================================================== */

/* current-page state for a .pill used as a route switcher */
.pill.on{color:var(--tx);border-color:var(--ac);font-weight:600}

/* wide tables must scroll inside their own container, never the page body */
.tblwrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.tblwrap table{min-width:760px}
/* A focusable scroll container needs a visible focus ring, or keyboard users
   cannot tell what they are about to scroll. */
.tblwrap:focus-visible,.cscroll:focus-visible{outline:2px solid var(--ac);outline-offset:2px}
/* Prose tables are NOT data tables. The 760px floor above exists for wide
   leaderboard-style tables; applied to the Privacy Policy's two-column purpose
   table it forced a scrollbar at every viewport. It stays a real <table> for
   accessibility -- it just sizes to its content and scrolls only if it must. */
.page-legal .tblwrap table{min-width:0}
/* Key/value and at-a-glance tables are narrow by nature. They still need a
   scroll container (a long model name can exceed 360px), but forcing the
   760px data-table floor on them would make every one of them scroll at
   every viewport. */
.tblwrap.fit table{min-width:0}

/* sortable table headers reuse the existing th treatment */
th.sortable{cursor:pointer;user-select:none;white-space:nowrap}
th.sortable:hover{color:var(--tx2)}
th.sortable .ind{color:var(--tx3);font-size:9px;padding-left:3px}
tr.hi td{background:var(--acw)}

/* index/listing grids */
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.mcard{background:var(--panel);border:1px solid var(--bd);border-radius:12px;padding:13px 14px;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:6px}
.mcard:hover{border-color:var(--ac)}
.mcard .mh{display:flex;align-items:center;gap:8px;font-size:13.5px;font-weight:600}
.mcard .mm{font-size:11px;color:var(--tx3)}

/* filter row: same visual language as .ctrl */
.filter{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 14px}
.filter input[type=search],.filter input[type=text],.filter select{
 font-size:12px;border:1px solid var(--bds);border-radius:7px;padding:6px 11px;
 color:var(--tx);background:var(--panel);font-family:inherit}
.filter input[type=search]{min-width:230px}
input[type=email]{padding:9px 12px;border:1px solid var(--bds);border-radius:8px;background:var(--panel);color:var(--tx);font-size:13px;font-family:inherit}

/* recommender weight sliders */
.wrow{display:flex;align-items:center;gap:10px;margin:10px 0;font-size:12px;color:var(--tx2)}
.wrow label{width:110px}
.wrow input[type=range]{flex:1;accent-color:var(--ac)}
.wrow output{width:44px;text-align:right;color:var(--tx);font-weight:600}

/* Legal documents. The sticky left nav links to heading ids, and the sticky
   header would otherwise cover the target — .sec carries scroll-margin-top for
   the same reason, but these headings are plain h2/h3 inside .copy. */
.page-legal .copy h2,.page-legal .copy h3{scroll-margin-top:70px}
.page-legal .copy table{margin:12px 0}
.page-legal .copy li{margin:4px 0}

/* prose pages (methodology, attribution, about) */
.copy{max-width:760px}
.copy h2{font-size:19px;font-weight:600;margin:26px 0 8px;letter-spacing:-.2px}
.copy h3{font-size:15px;font-weight:600;margin:18px 0 6px}
.copy p,.copy li{font-size:13.5px;color:var(--tx2);line-height:1.65}
.copy a{color:var(--ac);text-decoration:none;overflow-wrap:anywhere}
.copy a:hover{text-decoration:underline}
/* Long URLs inside inline <code> were the actual cause of legal-page overflow:
   code does not wrap at arbitrary points, so a single URL pushed the document
   wider than the viewport. `anywhere` also lets the line box shrink, which
   break-word alone does not do. Content is never shortened to fit. */
.copy code{overflow-wrap:anywhere;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;background:var(--panel2);border-radius:4px;padding:1px 5px}

/* skip link for keyboard users */
.skip{position:absolute;left:-9999px}
.skip:focus{left:22px;top:8px;z-index:60;background:var(--panel);border:1px solid var(--ac);
 border-radius:8px;padding:8px 12px;font-size:13px;color:var(--tx)}

@media(max-width:1000px){.grid2,.grid4{grid-template-columns:1fr}}

/* ======================================================================== *
 * 9. RESPONSIVE — 360px floor
 *
 * The reference screenshots are an iPhone 16 Pro Max at 440px CSS px, one of
 * the WIDEST phones sold. Anything that overflows there overflows worse on
 * every smaller device, so the floor targeted here is 360px.
 *
 * The rule: nothing may cause horizontal PAGE scroll. Wide content scrolls
 * inside its own container. Measured, not eyeballed -- documentElement
 * .scrollWidth must equal .clientWidth on every page type at 360/390/440.
 *
 * Before this block, all 45 page x viewport combinations overflowed, every
 * page reporting a constant scrollWidth of 872px: the header pill strip is
 * flex-nowrap and simply did not fit, so the widest element set the page
 * width regardless of viewport.
 * ======================================================================== */

/* ---------------------------------------------------------------- nav drawer */
.burger{display:none;align-items:center;justify-content:center;width:34px;height:34px;flex:0 0 34px;
  background:transparent;border:1px solid var(--bd);border-radius:9px;cursor:pointer;color:var(--tx2);padding:0}
.burger:hover{color:var(--tx);border-color:var(--bds)}
.burger svg{width:17px;height:17px}
.dov{position:fixed;inset:0;background:var(--scrim);opacity:0;pointer-events:none;
  transition:opacity .2s ease;z-index:50}
.dov.open{opacity:1;pointer-events:auto}
.drawer{position:fixed;top:0;bottom:0;left:0;width:min(80vw,310px);z-index:60;background:var(--bg);
  border-right:1px solid var(--bd);transform:translateX(-100%);transition:transform .2s ease;
  overflow-y:auto;padding:12px 14px 22px;visibility:hidden}
.drawer.open{transform:none;visibility:visible}
.drawer .dhead{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding-bottom:10px;margin-bottom:8px;border-bottom:1px solid var(--bd)}
.drawer .dclose{background:transparent;border:1px solid var(--bd);border-radius:9px;width:32px;height:32px;
  cursor:pointer;color:var(--tx2);display:flex;align-items:center;justify-content:center;padding:0}
.drawer .dclose:hover{color:var(--tx);border-color:var(--bds)}
.drawer .dclose svg{width:15px;height:15px}
.drawer nav{display:flex;flex-direction:column;gap:2px}
.drawer nav a{color:var(--tx2);text-decoration:none;font-size:14px;padding:9px 10px;border-radius:9px}
.drawer nav a:hover{background:var(--panel2);color:var(--tx)}
.drawer nav a.on{background:var(--panel);color:var(--tx);font-weight:600}
.drawer .dmeta{margin-top:14px;padding-top:12px;border-top:1px solid var(--bd)}
body.navlock{overflow:hidden}

/* ------------------------------------------------- chart horizontal scroller */
/* Bars keep their width and the -58deg labels keep their geometry; the CHART
   scrolls inside this box instead of the page. .bars and .axis must live in ONE
   scroller or the labels desync from the bars they name. Bar count is never
   reduced: a leaderboard showing 12 of 22 models on a phone is a different
   claim from one showing all 22. */
/* overflow-x:auto makes this a scroll container in BOTH axes -- per CSS Overflow 3,
   overflow-y:visible computes to auto once overflow-x is not visible. That is still
   true, and it is why the -58deg labels' spill below .lblbox becomes VERTICAL scroll
   range on 2,771 charts.

   This rule used to carry `padding-top:18px;margin-top:-18px`. That pair existed to
   stop .bval.out being clipped -- 8 of its 15px -- back when the label anchored to
   .bcol and sat 8px ABOVE .bars' content top. It no longer does: it anchors to .bar
   and the plot reserves a 12% headroom band, so the topmost painted pixel of any
   chart in the build is 14.2px BELOW the content edge and a clip here cuts nothing.

   The pair was ALSO the cause of charts painting over their subtitle. overflow clips
   at the PADDING box, so the 18px band sat inside the scrollport, and margin-top:-18px
   lifted it over the preceding .csub or .ctrl. Empty at scrollTop 0 -- which is why
   recomputing box positions there showed a 0.0px difference and wrongly cleared it --
   and occupied the moment anything scrolled. Measured: clearance went +31.2px to
   -14.8px on Speed. See DESIGN-LOCK §10, 27 Jul, second entry.

   Removing both is layout-neutral (they cancelled), and it takes the 8.0px .ctrl
   overlap that HARD RULE 3 was written about down to 0.0px. Do not reintroduce
   either without re-reading that entry. */
.cscroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
.cinner{min-width:100%}

@media(max-width:900px){
  nav.top{display:none}
  .burger{display:inline-flex}
  /* The "Updated" pill moves into the drawer rather than being dropped -- it is
     the freshness signal and removing it would change what the page claims. */
  .hrow>.pill{display:none}
  .hrow{gap:9px}
  .wrap{padding:0 14px}
  /* Give every bar a fixed footprint so the series keeps its shape and scrolls. */
  .cinner{min-width:max-content}
  .bcol,.acol{flex:0 0 30px;min-width:30px}
  .bars .gl{left:0;right:0}
}

@media(max-width:700px){
  h1{font-size:27px;letter-spacing:-.3px}
  .page-model h1{font-size:24px}
  .sumgrid{gap:10px}
}

/* ------------------------------------------------------ mobile section nav */
/* Below 1000px .snav is display:none. On /privacy/ and /terms/ that sticky list
   is the ONLY way through a 12- and an 18-section document, so hiding it left
   those pages with no navigation at all on a phone. This is the equivalent. */
.jump{display:none;margin:14px 0 4px;border:1px solid var(--bd);border-radius:10px;background:var(--panel)}
.jump>summary{cursor:pointer;padding:10px 13px;font-size:13px;font-weight:600;color:var(--tx);
  list-style:none;display:flex;align-items:center;justify-content:space-between;gap:8px}
.jump>summary::-webkit-details-marker{display:none}
.jump>summary:after{content:"";width:7px;height:7px;border-right:1.5px solid var(--tx3);
  border-bottom:1.5px solid var(--tx3);transform:rotate(45deg);transition:transform .15s ease;margin-bottom:3px}
.jump[open]>summary:after{transform:rotate(-135deg);margin-bottom:-2px}
.jump>summary:focus-visible{outline:2px solid var(--ac);outline-offset:-2px;border-radius:10px}
.jump nav{display:flex;flex-direction:column;padding:2px 8px 10px}
.jump nav a{color:var(--tx2);text-decoration:none;font-size:13px;padding:7px 9px;border-radius:8px}
.jump nav a:hover{background:var(--panel2);color:var(--tx)}

@media(max-width:1000px){
  .jump{display:block}
  /* A grid item's automatic minimum size is its MIN-CONTENT size, so `1fr` alone
     cannot shrink below the widest thing inside -- here the chart's max-content
     inner track. The column therefore floored at ~744px and every sibling, .jump
     included, inherited that width. minmax(0,1fr) plus min-width:0 is what
     actually lets the scroll containers do their job. */
  .layout{grid-template-columns:minmax(0,1fr)}
  .layout>*{min-width:0}
  /* Same trap, every other grid on the site: `1fr` is minmax(auto,1fr) and the
     auto floor is min-content, so one unwrappable flex row inside a card sets the
     whole column's width. Every grid gets minmax(0,1fr) and every grid child
     min-width:0, or the scroll containers below never get a chance to scroll. */
  .g3,.promo,.ann,.grid2,.grid4{grid-template-columns:minmax(0,1fr)}
  /* .sumgrid is the exception: the model page's five-metric row steps
     5 -> 2 -> 1, not 5 -> 1. Folding it into the single-column rule above
     silently deleted the 2-column step between 700px and 1000px. */
  .sumgrid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .g3>*,.promo>*,.ann>*,.grid2>*,.grid4>*,.sumgrid>*,.card{min-width:0}
  /* The chart title row and control row are flex with no wrap; on a phone they
     are the widest thing in the card and would otherwise set its min-content. */
  .ctitle,.cbar,.chead{flex-wrap:wrap}
  .ctitle{row-gap:4px}
  /* Selects and inputs must never set the page width. */
  select,input,textarea{max-width:100%}
  .sel,.ctrl{flex-wrap:wrap}
}

/* Motion: the drawer and the jump chevron are the only new transitions, and both
   must stop under prefers-reduced-motion -- the field-notes strip already does. */
@media(prefers-reduced-motion:reduce){
  .drawer,.dov,.jump>summary:after{transition:none}
}

/* Order matters: this must follow the max-width:1000px block above, or the
   2-column rule there wins at every width below 700px too and the final
   single-column step never happens. Both blocks match at 360px; the later one
   applies. Keeping it last is the whole reason it works. */
@media(max-width:700px){
  .sumgrid{grid-template-columns:minmax(0,1fr)}
  /* Two hardcoded 1.55fr/1fr grids (model page Summary + Technical specs, and the
     comparison-page equivalent) matched no responsive selector, so at 360px they
     stayed two columns of roughly 190px and 120px. They cause no PAGE overflow,
     which is exactly why the scrollWidth measurement never flagged them. */
  .split{grid-template-columns:minmax(0,1fr)}
}
