/* ─── PerfSections stylesheet ────────────────────────────────────────
   Extracted verbatim from index.html's <style> (Wave C1 — see
   plans/i-figured-it-out-soft-willow.md §3, §8 Wave C1). Class names keep their
   exact spelling — this file has a documented .a/.b/.bento collision history, so
   renaming anything here is how a silent regression happens. Covers the
   section/tile system (.sec, .toplevel, .tl-*, .cell*, .bk*, .rank-*, .donut-*,
   .fnl*, .snk*, .split*, .dir*, .pill, .num-* odometer, .serp-trend*) plus the
   AI-analysis orb (.an-*) rendered by assets/analysis-tile.js — there is no
   separate analysis-tile.css, so its styles live here too. Rules belonging to
   the grid page itself (tiles grid, hero, mesh, toast, dead bento/bk cards) stay
   in index.html. */

/* split out of index.html's combined mono-numerals rule — only the
   section-system half of that selector list */
.rank-bar-pos,.donut-center-num,.donut-leg strong,.priority-num,.pill,.tl-num,.tl-split,.cell-num,.bk-row-v,.bk-row-sub,.num-strip .num-d{font-family:var(--mono);text-transform:uppercase}
/* split out of index.html's combined overline rule — only the section-system half */
.donut-center-lbl,.tl-lbl,.sec-title,.bk-title,.an-kicker,.an-sec-h{font-family:var(--mono)}

/* Top Level — no card, sits on modal bg */
.toplevel{padding:2px 2px 6px}
.toplevel-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:26px}
.tl-stat{display:flex;justify-content:space-between;gap:24px;flex-direction:column;padding:3rem}
.tl-stat-main{min-width:0}
.tl-num{font-size:40px;font-weight:300;letter-spacing:-0.04em;line-height:1;color:var(--text);font-variant-numeric:tabular-nums}
.tl-lbl{font-size:10.5px;text-transform:uppercase;letter-spacing:0.12em;color:var(--muted);margin-top:9px;display:flex;align-items:center;gap:8px}
.tl-split{font-size:10.5px;color:var(--dim);margin-top:6px;font-variant-numeric:tabular-nums}
.tl-spark{width:100%;height:25%;flex-shrink:0;position:relative}
.tl-spark svg{width:100%;height:100%;display:block;overflow:visible}
/* glow dot at the head (latest point) of the top-level sparkline */
.spark-head{position:absolute;left:99.3%;margin:-4px 0 0 -4px;width:8px;height:8px;border-radius:50%;opacity:0;pointer-events:none}

/* Section (outer box) — title carries the section label (no dividers) */
/* Sections are no longer tiles — they sit straight on the page. */
.sec{padding:0;position:relative}
/* Air between stacked sections — labels were sitting on the bottom edge of the
   section above. Sibling rule so a lone section (or the first) gains nothing. */
.sec + .sec,.toplevel + .sec,.cp-toplevel-row + .sec{margin-top:60px}
.sec-title{text-align:center;font-size:12px;font-weight:600;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-bottom:20px;display:flex;align-items:center;justify-content:left;gap:9px}
.sec-title::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--pos);box-shadow:0 0 8px var(--pos)}
.sec-ask{margin-left:auto;font-family:var(--mono);font-size:9.5px;letter-spacing:0.1em;text-transform:uppercase;background:var(--surface);border:1px solid var(--border);color:var(--muted);border-radius:7px;padding:4px 9px;cursor:pointer;transition:0.18s}
.sec-ask:hover{background:var(--surface-hi);color:var(--text);border-color:var(--border-hi)}

/* No-data fallback used by PerfSections' Ads-section empty state */
.empty{padding:60px 20px;text-align:center;color:var(--dim);font-size:13px}

.pill{display:inline-flex;align-items:center;gap:3px;font-size:10px;font-weight:600;padding:2px 7px;border-radius:100px;letter-spacing:-0.005em;white-space:nowrap}
.pill.pos{color:var(--pos);background:rgba(74,222,128,0.1)}
.pill.neg{color:var(--neg);background:rgba(248,113,113,0.1)}
.pill.neu{color:var(--muted);background:var(--surface-2)}
/* Neutral data mode (Settings → Data colours): verdict pills lose the
   green/red and wear the actual pearl MATERIAL — dark text on the drifting
   iridescent white, arrows still say the direction. The material itself is
   defined once in the neutral block at the end of this file. */
html.data-neutral .pill.pos,html.data-neutral .pill.neg{
  color:#23233B;
  background:var(--pearl-hi),var(--pearl-iri),var(--pearl-base);
  background-size:100% 100%,240% 240%,100% 100%;
  animation:psPearlDrift 7s ease-in-out infinite}

/* Inner metric cells */
/* Bento: a 12-column bed so cells can take different weights. The metrics that
   carry a sparkline go XL — bigger number, taller graph, double width — and the
   flat ones fill in around them. Spans always total 12 per row, so it packs clean. */
.cell-grid{display:grid;gap:11px}
.cell-grid.g12{grid-template-columns:repeat(12,minmax(0,1fr))}
/* 15 columns where a row wants fifths (6+6+3) and the next wants thirds (5+5+5) —
   12 can't do both, 15 does each exactly. 30 covers fifths AND sixths AND thirds. */
.cell-grid.g15{grid-template-columns:repeat(15,minmax(0,1fr))}
.cell-grid.g30{grid-template-columns:repeat(30,minmax(0,1fr))}
/* A column that holds its own rows and still occupies one slot of the bed. Its
   children grow to fill the row's height, so the column ends level with the tiles
   beside it instead of leaving dead space under the last card. */
.stack{display:flex;flex-direction:column;gap:11px;min-width:0}
.stack > .cell{flex:1.35}
.stack > .stack-2{flex:1}
.stack-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:11px}
.stack.s4{grid-column:span 4}
.stack.s5{grid-column:span 5}
.stack.s10{grid-column:span 10}
.cell.s5{grid-column:span 5}
.cell.s10{grid-column:span 10}
.cell.s18{grid-column:span 18}
.cell.s2{grid-column:span 2}
.cell.s3{grid-column:span 3}
.cell.s4{grid-column:span 4}
.cell.s6{grid-column:span 6}
.cell.s8{grid-column:span 8}
.cell.xl{padding:22px 24px}
.cell.xl .cell-num{font-size:38px;letter-spacing:-0.035em}
.cell.xl .cell-lbl{margin-top:11px}
.cell.xl .cell-spark{height:58px;margin-top:auto;padding-top:16px}
.cols-4{grid-template-columns:repeat(4,1fr)}
.cols-3{grid-template-columns:repeat(3,1fr)}
.cols-2{grid-template-columns:repeat(2,1fr)}
/* Metric cells and breakdown boxes get the same treatment as the client tiles and
   the Today widgets: cursor-tracked sheen (--mx/--my), soft outer glow, GSAP tilt. */
.cell,.bk{position:relative;transition:border-color 0.3s ease,background 0.3s ease}
.cell::before,.bk::before{content:'';position:absolute;inset:0;border-radius:14px;
  background:radial-gradient(150% 150% at var(--mx,50%) var(--my,50%),var(--tile-sheen),rgba(255,255,255,0.04) 28%,rgba(255,255,255,0.012) 55%,transparent 82%);
  opacity:0;transition:opacity 0.45s var(--ease);pointer-events:none}
.cell::after,.bk::after{content:'';position:absolute;top:-1px;left:-1px;right:-1px;bottom:-1px;
  border-radius:14px;box-shadow:0 0 32px var(--border-hi);opacity:0;z-index:-1;
  transition:opacity 0.5s var(--ease);pointer-events:none}
.cell > *,.bk > *{position:relative;z-index:1}
.cell:hover,.bk:hover{border-color:var(--border-hi);background:var(--card-hi)}
.cell:hover::before,.bk:hover::before{opacity:0.38}
.cell:hover::after,.bk:hover::after{opacity:0.28}
.cell{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:15px 16px;min-width:0;
  display:flex;flex-direction:column;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px)}
.cell-num{font-size:26px;font-weight:300;letter-spacing:-0.03em;line-height:1;color:var(--text);font-variant-numeric:tabular-nums}
.cell-lbl{font-size:10px;text-transform:uppercase;letter-spacing:0.09em;color:var(--muted);margin-top:9px;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.cell-spark{height:32px;margin-top:auto;padding-top:11px}   /* sits on the floor, whatever the row height */
.cell-spark svg{width:100%;height:100%;display:block;overflow:visible}

/* Sankey — three steps across, green where people carry on and red where they
   drop. One value→pixel scale across all three columns, so the bands visibly thin
   out step by step; the red is the difference. Labels are HTML pinned to the same
   pixel rows (the SVG's viewBox height equals its CSS height, so only x stretches). */
.snk{position:relative}
.snk-svg{width:100%;display:block;overflow:visible}
.snk-lbl{position:absolute;font-size:9.5px;line-height:1.2;color:var(--text);letter-spacing:-0.005em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none;max-width:29%}
.snk-lbl b{font-family:var(--mono);font-weight:500;font-size:8.5px;color:var(--dim);margin-left:5px}
.snk-steps{display:flex;margin-bottom:9px;font-family:var(--mono);font-size:8.5px;
  letter-spacing:0.11em;text-transform:uppercase;color:var(--dim)}
.snk-steps span{flex:1}
.snk-steps span:nth-child(2){text-align:center}
.snk-steps span:nth-child(3){text-align:right}
.snk-rib{transition:opacity 0.2s var(--ease)}
.snk:hover .snk-rib{opacity:0.3}
.snk-rib:hover{opacity:1}
.snk-foot{display:flex;justify-content:flex-end;gap:14px;margin-top:10px;
  font-family:var(--mono);font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;color:var(--dim)}
.snk-foot i{font-style:normal;display:inline-flex;align-items:center;gap:5px}
.snk-foot i::before{content:'';width:8px;height:3px;border-radius:2px;background:var(--pos)}
.snk-foot i.drop::before{background:var(--neg)}

/* Split bar — one line, filled from the left for the first share and from the
   right for the second. Compact enough to sit in a metric row.
   NB: bare .a/.b would collide with the bento block classes — always prefix. */
.split{display:flex;flex-direction:column;justify-content:flex-end;flex:1;padding-top:2px}
.split-bar{display:flex;gap:3px;height:6px}
.split-seg{border-radius:100px;min-width:2px}
.split-lead{background:var(--pos)}
.split-rest{background:color-mix(in srgb,var(--pos) 26%,transparent)}
.split-ends{display:flex;justify-content:space-between;gap:10px;margin-top:11px;
  font-family:var(--mono);font-size:9px;letter-spacing:0.06em;text-transform:uppercase;color:var(--muted)}
.split-ends span{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.split-ends span:last-child{text-align:right}
.split-ends b{font-weight:500;color:var(--text)}

/* Traffic direction — one track per page, split at a centre tick: what arrives on
   the left, what carries on to another page on the right. A page with a long left
   bar and a stub on the right is where journeys stop. */
.dir-row{padding:9px 0;opacity:var(--rank-op,1);transition:opacity 0.25s var(--ease)}
.dir-row:hover{opacity:1}
.dir-top{display:flex;align-items:baseline;gap:16px}
.dir-k{flex:1;min-width:0;font-size:12px;color:var(--text);letter-spacing:-0.005em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dir-track{display:flex;align-items:center;gap:5px;margin-top:8px}
.dir-half{flex:1;height:5px;background:var(--surface-2);border-radius:100px;position:relative;overflow:hidden}
.dir-fill{position:absolute;top:0;bottom:0;border-radius:100px}
.dir-half.in .dir-fill{right:0;background:color-mix(in srgb,var(--pos) 55%,transparent)}
.dir-half.on .dir-fill{left:0;background:var(--pos)}
.dir-half.on .dir-fill.stop{background:var(--neg)}
.dir-mid{width:1px;height:11px;background:var(--border-hi);flex-shrink:0}
.dir-tag{font-family:var(--mono);font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;
  color:var(--dim);flex-shrink:0}
.dir-tag.stop{color:var(--neg)}
.dir-tag.hub{color:var(--pos)}

/* ── Visual data tiles: funnel · gauge · bubble plot ───────────────
   All three live inside a .bk box, so they inherit its tilt + sheen. Shapes are
   SVG; every label is HTML on top, so type stays at its real size no matter how
   wide the box gets. */
/* Funnel, landscape: stages run left to right and the walls close in as they go.
   Reads naturally in a wide box, and the stage labels sit in a row beneath. */
.fnl{display:flex;flex-direction:column}
.fnl-svg{width:100%;height:132px;display:block;overflow:visible}
.fnl-cols{display:flex;margin-top:12px}
.fnl-col{flex:1;min-width:0;text-align:center;padding:0 4px;position:relative}
.fnl-col + .fnl-col::before{content:'';position:absolute;left:0;top:3px;bottom:3px;width:1px;background:var(--border)}
.fnl-v{font-family:var(--mono);font-size:15px;color:var(--text);font-variant-numeric:tabular-nums;line-height:1}
.fnl-k{font-size:10px;letter-spacing:0.09em;text-transform:uppercase;color:var(--muted);margin-top:7px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:var(--mono)}
.fnl-step{display:inline-block;margin-top:7px;font-family:var(--mono);font-size:9px;letter-spacing:0.08em;
  text-transform:uppercase;color:var(--dim);border:1px solid var(--border);border-radius:100px;padding:2px 7px;white-space:nowrap}

/* Rankings bar chart */
.rank-list{display:flex;flex-direction:column;gap:10px;margin-top:4px;position:relative;z-index:1}
.rank-bar{display:grid;grid-template-columns:1fr auto;gap:16px;align-items:center;
  opacity:var(--rank-op,1);transition:opacity 0.25s var(--ease)}
.rank-bar:hover{opacity:1}
.rank-bar-kw{
  font-size:12.5px;color:var(--text);letter-spacing:-0.005em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.rank-bar-track{
  position:relative;height:6px;background:var(--surface-2);border-radius:100px;
  overflow:hidden;margin-top:5px;
}
.rank-bar-fill{
  position:absolute;left:0;top:0;bottom:0;
  border-radius:100px;
  background:linear-gradient(90deg, var(--pos), color-mix(in srgb, var(--pos), white 25%));
  transform-origin:left center;
}
/* Slipped since the last check — the bar takes the trend's colour, not the rank's. */
.rank-bar-fill.down{background:linear-gradient(90deg, var(--neg), color-mix(in srgb, var(--neg), white 25%))}
.rank-bar-pos{
  font-size:12px;font-weight:500;color:var(--muted);
  font-variant-numeric:tabular-nums;white-space:nowrap;letter-spacing:-0.005em;
  display:grid;grid-template-columns:40px 42px 54px;gap:10px;align-items:baseline;
}
.rank-bar-pos.win{color:var(--brand-color);font-weight:600}
.rank-bar-pos.weak{color:var(--dim)}
/* Best-ever rank. Deliberately dim and never inheriting .win/.weak — it is
   reference, not standing, and must not compete with the live position. */
.rank-bar-pos .rank-bar-best{color:var(--dim);font-weight:400}
/* Live SERPWatcher extras: movement arrows, volume tag, section meta */
/* Movement uses the shared .pill chip — same shape and colour language as every
   percentage delta on the page, so up/down reads identically wherever you look. */
.rank-vol{font-size:10.5px;color:var(--dim);margin-left:7px;font-family:var(--mono)}
.sec-sub{margin-left:auto;font-size:9.5px;font-weight:400;letter-spacing:0.1em;text-transform:uppercase;color:var(--dim);text-align:right}
@media(max-width:640px){.sec-sub{display:none}}

/* Rank tier donut */
.donut-wrap{position:relative;width:140px;height:140px;margin:0 auto;flex-shrink:0;z-index:1}
.donut-center{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;pointer-events:none}
.donut-center-num{font-size:24px;font-weight:400;color:var(--text);letter-spacing:-0.02em;line-height:1;font-variant-numeric:tabular-nums}
.donut-center-lbl{font-size:9.5px;color:var(--muted);letter-spacing:0.12em;text-transform:uppercase;margin-top:5px;font-weight:500}
.donut-legend{display:flex;flex-direction:column;gap:8px;margin-top:18px;flex:1;justify-content:center}
.donut-leg{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--muted);letter-spacing:-0.005em;
  cursor:default;transition:opacity 0.2s var(--ease),color 0.2s var(--ease)}
/* While a segment (or its legend row) is hovered, everything else recedes so the
   pair reads as one thing. Driven by attachDonutHover — the two are separate DOM
   subtrees, so CSS alone can't link them. */
.donut-wrap circle{transition:opacity 0.2s var(--ease)}
.bk-donut.hl .donut-wrap circle{opacity:0.22}
.bk-donut.hl .donut-wrap circle.on{opacity:1}
.bk-donut.hl .donut-leg{opacity:0.3}
.bk-donut.hl .donut-leg.on{opacity:1;color:var(--text)}
.donut-leg-dot{width:8px;height:8px;border-radius:2px;flex-shrink:0}
.donut-leg strong{color:var(--text);font-weight:500;margin-left:auto;font-variant-numeric:tabular-nums}

/* Priorities (Progress section — noteItem) */
.priority-item{display:flex;gap:14px;padding:13px 0;border-bottom:1px solid var(--border);align-items:flex-start;position:relative;z-index:1}
.priority-item:last-child{padding-bottom:0;border-bottom:none}
.priority-item:first-child{padding-top:6px}
.priority-num{
  font-size:11px;font-weight:600;color:var(--muted);min-width:24px;font-variant-numeric:tabular-nums;
  padding-top:2px;letter-spacing:0.04em;
}
.priority-text{font-size:13.5px;line-height:1.55;color:var(--text);letter-spacing:-0.005em;flex:1}
.priority-text .keyword{color:var(--brand-color);font-weight:500}
.priority-text .high{
  display:inline-block;padding:1px 7px;border-radius:100px;font-size:10px;font-weight:600;letter-spacing:0.08em;
  background:rgba(248,113,113,0.12);color:var(--neg);margin-left:4px;text-transform:uppercase;
}
/* Human summary + collapsible technical detail */
.pi-human{display:inline}
.pi-toggle{
  display:inline-flex;align-items:center;gap:4px;margin-left:8px;padding:1px 8px;vertical-align:middle;
  font-family:var(--mono);font-size:9.5px;font-weight:600;letter-spacing:0.09em;text-transform:uppercase;
  color:var(--muted);background:var(--faint,rgba(127,127,127,0.08));border:1px solid var(--border);
  border-radius:100px;cursor:pointer;transition:color .15s,background .15s,border-color .15s;white-space:nowrap;
}
.pi-toggle:hover{color:var(--text)}
.pi-toggle::after{content:"›";display:inline-block;transition:transform .18s;font-weight:700;font-size:12px;line-height:1}
.pi-toggle.open::after{transform:rotate(90deg)}
.pi-toggle.open{color:var(--text);border-color:var(--brand-color)}
.pi-detail{
  margin-top:8px;padding:9px 12px;border-left:2px solid var(--border);
  font-size:12px;line-height:1.6;color:var(--muted);letter-spacing:-0.003em;
  background:var(--faint,rgba(127,127,127,0.05));border-radius:0 6px 6px 0;
}
.pi-detail strong{color:var(--text);font-weight:600}
.priority-item{display:flex;gap:18px;padding:16px 0;border-bottom:1px solid var(--border);align-items:flex-start}
.priority-item:last-child{padding-bottom:0;border-bottom:none}
.priority-item:first-child{padding-top:0}
.priority-num{
  font-size:11px;font-weight:600;color:var(--muted);min-width:24px;font-variant-numeric:tabular-nums;
  padding-top:3px;letter-spacing:0.04em;
}
.priority-text{font-size:13.5px;line-height:1.55;color:var(--text);letter-spacing:-0.005em;flex:1}
.priority-text .keyword{color:var(--brand-color);font-weight:500}
.priority-text .high{
  display:inline-block;padding:1px 7px;border-radius:100px;font-size:10px;font-weight:600;letter-spacing:0.08em;
  background:rgba(248,113,113,0.12);color:var(--neg);margin-left:4px;text-transform:uppercase;
}

/* Breakdown boxes (bars / donut / notes) */
.bk-grid{display:grid;gap:11px}
/* Same 12-column bed as the metric cells, so a fancy tile can be a quarter-width
   dial next to a two-thirds funnel instead of everything sitting in equal halves. */
.bk-grid.g12{grid-template-columns:repeat(12,minmax(0,1fr))}
.bk.s4{grid-column:span 4}
.bk.s5{grid-column:span 5}
.bk.s10{grid-column:span 10}
.bk.s20{grid-column:span 20}
.bk.s6{grid-column:span 6}
.bk.s8{grid-column:span 8}
.bk.s12{grid-column:span 12}
.bk-grid.cols-2 > :last-child:nth-child(odd){grid-column:1 / -1}   /* lone box spans full width */
.bk{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:16px 18px;min-width:0;
  backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px)}
.bk-title{font-size:10.5px;text-transform:uppercase;letter-spacing:0.1em;color:var(--muted);font-weight:500;margin-bottom:12px}
/* Column headers — they reuse the rows' own grid, so a header can never drift out
   of line with the numbers under it. Naming the columns once here is what lets the
   rows drop their per-value labels. */
.bk-head{display:flex;align-items:center;gap:16px;padding-bottom:7px;margin-bottom:3px;border-bottom:1px solid var(--border)}
.bk-head-k{flex:1;min-width:0}
.bk-head .bk-row-v,.rank-head .rank-bar-pos{font-family:var(--mono);font-size:8.5px;font-weight:500;
  letter-spacing:0.11em;text-transform:uppercase;color:var(--dim)}
.rank-head{display:grid;grid-template-columns:1fr auto;gap:16px;align-items:center;
  padding-bottom:7px;margin-bottom:3px;border-bottom:1px solid var(--border)}
/* Ranked rows fade with their standing — the leader reads at full strength, the
   tail recedes. --rank-op is set per row from its share of the top value. Hovering
   a row brings it back to full so nothing is unreadable when you go looking. */
.bk-row{display:flex;align-items:center;gap:16px;padding:7px 0;
  opacity:var(--rank-op,1);transition:opacity 0.25s var(--ease)}
.bk-row:hover{opacity:1}
.bk-row:first-child{padding-top:0}
.bk-row:last-child{padding-bottom:0}
.bk-row-main{flex:1;min-width:0}
.bk-row-k{font-size:12px;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bk-row-bar{position:relative;height:4px;background:var(--surface-2);border-radius:100px;overflow:hidden;margin-top:5px}
.bk-row-bar-fill{position:absolute;left:0;top:0;bottom:0;border-radius:100px;background:linear-gradient(90deg,var(--pos),color-mix(in srgb,var(--pos),white 30%))}
/* Value and sub-value are their own fixed columns, left-aligned and spaced apart,
   so each metric lines up down the list rather than ragging off the right edge. */
.bk-row-v{flex-shrink:0;font-size:12px;font-weight:600;color:var(--text);font-variant-numeric:tabular-nums;
  display:grid;grid-template-columns:48px 44px;gap:12px;align-items:baseline}
  /* both columns fixed: an auto last column collapses on rows that have no sub,
     which shifts the value column and loses the alignment this is for */
.bk-row-sub{font-size:10px;color:var(--dim);font-weight:500}
.bk-donut{display:flex;flex-direction:column}
.bk-donut .bk-donut-wrap{display:flex;align-items:center;justify-content:center;gap:28px;flex:1}
.bk-donut .donut-legend{flex:0 1 auto;min-width:170px}
.bk-col{display:flex;flex-direction:column;gap:11px;min-width:0}
.bk-col .bk{flex:1}
.serp-trend-head{display:flex;align-items:baseline;gap:10px;margin-bottom:10px}
.serp-trend-num{font-family:var(--mono);font-size:26px;color:var(--text);font-variant-numeric:tabular-nums}
.serp-trend-sub{font-size:10.5px;color:var(--dim);text-transform:uppercase;letter-spacing:0.08em}
.serp-trend-spark{height:56px;margin-top:6px}
.serp-trend-spark svg{width:100%;height:100%;display:block;overflow:visible}
.pi-tag{display:inline-block;font-family:var(--mono);font-size:8.5px;letter-spacing:0.08em;text-transform:uppercase;color:var(--dim);border:1px solid var(--border);padding:1px 6px;border-radius:100px;margin-right:7px;vertical-align:2px}
.bk-donut .donut-wrap{margin:0}
.bk-donut .donut-legend{margin-top:0;gap:9px}
.bk .priority-item{padding:11px 0}
.bk .priority-item:first-child{padding-top:0}

@media(max-width:980px){
  /* half the bed: an XL cell takes the full row, a small one takes half */
  .cell-grid.g12{grid-template-columns:repeat(6,minmax(0,1fr))}
  .cell.s6,.cell.s8{grid-column:span 6}
  .cell-grid.g15,.cell-grid.g30{grid-template-columns:repeat(6,minmax(0,1fr))}
  .cell.s8,.cell.s18,.cell.s20,.bk.s18,.bk.s20{grid-column:span 6}
  .cell.s5,.cell.s6,.cell.s10,.bk.s5,.bk.s6,.bk.s10,.stack.s10{grid-column:span 3}
  .stack.s4,.stack.s5{grid-column:span 3}
  .cell.s2{grid-column:span 2}
  .cell.s3,.cell.s4{grid-column:span 3}
  .tl-num{font-size:34px}   /* keep tile + Top Level identical — the number morphs between them */
}
@media(max-width:560px){
  /* Phones keep a 6-column bed so the compact metrics can pair up two to a row —
     stacking every single number full-width makes the page endless. Anything that
     carries a graph, a list or a legend still gets the full width.
     minmax(0,…) not 1fr: a bare 1fr is minmax(auto,1fr), so the track sizes to the
     cell's content and the page scrolls sideways instead of the cell shrinking. */
  .cell-grid.g12,.cell-grid.g15,.cell-grid.g30{grid-template-columns:repeat(6,minmax(0,1fr))}
  .bk-grid.g12,.bk-grid.cols-2{grid-template-columns:minmax(0,1fr)}
  /* Direct children only — a .cell nested inside a .stack lives in that stack's own
     2-column grid, and must not be given a span from the outer bed. */
  .cell-grid > .cell{grid-column:span 3}               /* compact metrics, 2 up */
  .cell-grid > .cell.xl{grid-column:1 / -1}            /* headline metrics, full width */
  /* .stack.sN (0,2,0) outranks a bare .stack, so name the variants explicitly. */
  .cell-grid > .bk,.bk-grid > .bk,.stack,.stack.s4,.stack.s5,.stack.s10{grid-column:1 / -1}
  .cell-num{font-size:24px}
  .cell.xl .cell-num{font-size:32px}
  .cell.xl .cell-num{font-size:32px}
  /* Titles: wrap instead of pushing the page sideways. */
  .sec-title,.bk-title,.cell-lbl,.tl-lbl{white-space:normal;overflow-wrap:anywhere}
  .bk-title{margin-bottom:10px}
  .fnl-k,.snk-lbl{font-size:9px}
  .snk-lbl{max-width:34%}
}
@media(max-width:760px){
  .toplevel-grid{grid-template-columns:1fr!important;gap:18px}   /* beats the inline column count */
  .cols-4{grid-template-columns:repeat(2,1fr)}
  .bk-grid.cols-2{grid-template-columns:minmax(0,1fr)}
  .bk-grid.g12{grid-template-columns:minmax(0,1fr)}
  .bk.s4,.bk.s5,.bk.s6,.bk.s8,.bk.s12{grid-column:1 / -1}
}

/* Per-character odometer number animation (tiles + modal) */
.num-roll{display:inline-block;white-space:nowrap}
.num-slot{display:inline-block;overflow:hidden;height:1em;line-height:1;vertical-align:bottom}
.num-strip{display:block}
.num-strip .num-d{display:block;height:1em;line-height:1;text-align:center;font-variant-numeric:tabular-nums}

/* ── AI analysis — orb → expanding tile (phase 2.5) ────────────────
   Rendered by assets/analysis-tile.js. No dedicated analysis-tile.css exists
   (only perf-sections.js/.css/analysis-tile.js are in scope for this extraction),
   so these rules live here — they're always loaded on the same page as the tile. */
.an-tile{position:relative;height:44px;flex-shrink:0}
.an-tile.open{height:auto;background:var(--surface);border:1px solid var(--border);border-radius:20px;overflow:hidden}
.an-aurora{position:absolute;left:0;top:0;width:132px;height:44px;border-radius:100px;overflow:hidden;clip-path:inset(0 round 22px);pointer-events:none;background:color-mix(in srgb,var(--bg) 86%,transparent);backdrop-filter:blur(18px) saturate(1.2);-webkit-backdrop-filter:blur(18px) saturate(1.2)}
.an-blobs{position:absolute;inset:-22%;opacity:0.62;transition:opacity .55s var(--ease)}
.an-tile.open .an-blobs{opacity:0.95}
.an-blobs .ab{position:absolute;mix-blend-mode:screen;border-radius:50%}
.an-blobs .ab.a1{background:radial-gradient(circle,#4F46E5,transparent 64%);width:90%;height:80%;left:-24%;bottom:-26%}
.an-blobs .ab.a2{background:radial-gradient(circle,#818CF8,transparent 64%);width:74%;height:66%;left:12%;bottom:16%}
.an-blobs .ab.a3{background:radial-gradient(circle,#22D3EE,transparent 64%);width:68%;height:60%;left:52%;bottom:-18%}
.an-blobs .ab.a4{background:radial-gradient(circle,#A78BFA,transparent 64%);width:78%;height:70%;left:40%;top:-12%}
.an-blobs .ab.a5{background:radial-gradient(circle,#F472B6,transparent 66%);width:60%;height:56%;left:-10%;bottom:28%}
.an-blobs .ab.a6{background:radial-gradient(circle,#6366F1,transparent 64%);width:64%;height:58%;left:24%;bottom:-30%}
.an-orb-hit{position:absolute;left:0;top:0;width:132px;height:44px;border-radius:100px;border:none;background:none;cursor:pointer;padding:0;z-index:3}
.an-orb-hit:focus{outline:none}
.an-orb-hit:focus-visible{outline:2px solid rgba(129,140,248,0.75);outline-offset:2px}
.an-orb-hit:hover ~ .an-aurora{filter:brightness(1.08)}
.an-tile.open .an-orb-hit{display:none}
.an-label{position:absolute;left:0;top:0;width:132px;height:44px;display:flex;align-items:center;justify-content:center;font-size:12.5px;font-weight:600;letter-spacing:0.01em;color:var(--text);pointer-events:none;z-index:2}
.an-close{position:absolute;top:12px;right:12px;z-index:3;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;border:1px solid var(--border);background:color-mix(in srgb,var(--card) 45%,transparent);color:var(--muted);font-size:15px;line-height:1;opacity:0;pointer-events:none;transition:color .2s,border-color .2s,transform .35s var(--ease)}
.an-tile.open .an-close{pointer-events:auto}
.an-close:hover{color:var(--text);border-color:var(--text);transform:rotate(90deg)}
.an-body{position:relative;z-index:1;padding:20px 22px;max-height:min(380px,50vh);overflow-y:auto;scrollbar-width:none;overscroll-behavior:contain}
.an-tile.deep .an-body{max-height:min(760px,80vh)}
.an-body::-webkit-scrollbar{display:none}
.an-tile:not(.open) .an-body{display:none}
.an-qhead{display:flex;align-items:center;gap:8px;margin-bottom:11px}
.an-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}
.an-dot.green{background:var(--pos);box-shadow:0 0 8px var(--pos)}
.an-dot.amber{background:#FBBF24;box-shadow:0 0 8px rgba(251,191,36,0.7)}
.an-dot.red{background:var(--neg);box-shadow:0 0 8px var(--neg)}
.an-kicker{font-size:10px;text-transform:uppercase;letter-spacing:0.13em;color:var(--muted);font-weight:600}
.an-summary{font-size:17px;line-height:1.65;color:var(--text);letter-spacing:-0.01em;max-width:72ch}
.anw{display:inline-block}
.an-after{margin-top:18px}
.an-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.an-btn{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;background:var(--surface);border:1px solid var(--border);color:var(--text);font-family:inherit;font-size:12px;font-weight:500;letter-spacing:-0.005em;border-radius:100px;cursor:pointer;transition:all 0.25s var(--ease)}
.an-btn:hover{background:var(--surface-hi);border-color:var(--border-hi);transform:translateY(-1px)}
.an-btn:active{transform:translateY(0) scale(0.98)}
.an-btn:disabled{opacity:0.45;cursor:default;transform:none}
.an-ghost{background:none;border:none;color:var(--dim);font-size:11.5px;cursor:pointer;font-family:inherit;padding:6px 2px;transition:color .2s}
.an-ghost:hover{color:var(--text)}
.an-meta{font-size:10.5px;color:var(--dim);margin-top:12px}
.an-sec-h{font-size:10.5px;text-transform:uppercase;letter-spacing:0.12em;color:var(--muted);font-weight:600;margin:20px 0 4px}
.an-sec-list{list-style:none;padding:0;margin:0}
.an-sec-list li{font-size:13px;line-height:1.65;color:var(--muted);padding:9px 0 9px 16px;position:relative;border-bottom:1px solid var(--border)}
.an-sec-list li:last-child{border-bottom:none}
.an-sec-list li::before{content:'';position:absolute;left:2px;top:16px;width:5px;height:5px;border-radius:50%;background:var(--border-hi)}
.an-sec-list li strong{color:var(--text)}
.an-sec-list li code{font-family:var(--mono);font-size:11px;background:var(--surface-hi);padding:1px 5px;border-radius:5px}
.an-skel{display:flex;flex-direction:column;gap:11px;padding-top:4px}
.an-skel-line{height:12px;border-radius:8px;background:color-mix(in srgb,#818CF8 9%,var(--surface));position:relative;overflow:hidden}
.an-skel-line::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,rgba(129,140,248,0.32),rgba(34,211,238,0.28),rgba(244,114,182,0.22),transparent);transform:translateX(-100%);animation:skelShimmer 1.1s ease-in-out infinite}
@keyframes skelShimmer{100%{transform:translateX(100%)}}
.an-skel-note{font-size:11px;color:var(--dim);margin-top:8px}
.an-err{font-size:12.5px;color:var(--neg);padding:6px 0}

/* ── Sparkline tooltips (perf-sections.js attachSparkTips) ──────────────
   One shared readout node for every spark on the page; the marker group is
   injected into whichever <svg> is being hovered. Both are pointer-transparent
   so they can never interrupt the hover they exist to serve. */
.spark-tip{position:fixed;z-index:400;pointer-events:none;opacity:0;transform:translateY(3px);
  background:var(--surface-hi,rgba(28,28,34,.96));border:1px solid var(--border-hi,rgba(255,255,255,.14));
  border-radius:9px;padding:6px 9px;box-shadow:0 10px 28px -8px rgba(0,0,0,.6);
  display:flex;flex-direction:column;gap:2px;white-space:nowrap;
  transition:opacity .14s var(--ease,ease),transform .14s var(--ease,ease)}
.spark-tip.on{opacity:1;transform:translateY(0)}
.spark-tip b{font-family:var(--mono);font-size:12px;font-weight:600;color:var(--text);letter-spacing:-0.01em}
.spark-tip i{font-family:var(--mono);font-style:normal;font-size:9.5px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted)}
.spark-tip-mark{pointer-events:none}
.spark-tip-mark .stm-guide{stroke:var(--border-hi,rgba(255,255,255,.22));stroke-width:1;stroke-dasharray:2 2}
.spark-tip-mark .stm-dot{fill:var(--text,#fff);stroke:var(--bg,#101014);stroke-width:1.5;
  vector-effect:non-scaling-stroke}

/* ─── Neutral data mode: the pearl, everywhere ─────────────────────────
   Settings → Data colours strips the green/red verdict palette. Sparklines
   already wear the pearl ramp (makeSparkSVG); this block gives every OTHER
   verdict surface the same material — the composer pearl's real three layers
   (white radial highlight + iridescent tint at 240% + white base, 7s drift),
   copied from portal.css .ptl-pearl. Copy the LAYERS, never a flattened
   gradient. Magnitude keeps riding on opacity (--rank-op etc.) untouched. */
html.data-neutral{
  --pearl-hi:radial-gradient(circle at 32% 26%, rgba(255,255,255,0.95), rgba(255,255,255,0) 58%);
  --pearl-iri:linear-gradient(120deg, rgba(129,140,248,0.34), rgba(244,114,182,0.26) 32%, rgba(34,211,238,0.30) 62%, rgba(167,139,250,0.32) 95%);
  --pearl-base:linear-gradient(160deg,#ffffff,#e9ecf6);
}
@keyframes psPearlDrift{0%,100%{background-position:0 0,0% 50%,0 0}50%{background-position:0 0,100% 50%,0 0}}
/* Bar fills: top-list bars, keyword rank bars (up AND slipped — the tooltip/pill
   still says which), the split-bar lead, the goes-on traffic half. */
html.data-neutral .bk-row-bar-fill,
html.data-neutral .rank-bar-fill,
html.data-neutral .rank-bar-fill.down,
html.data-neutral .split-lead,
html.data-neutral .dir-half.on .dir-fill,
html.data-neutral .dir-half.on .dir-fill.stop{
  background:var(--pearl-hi),var(--pearl-iri),var(--pearl-base);
  background-size:100% 100%,240% 240%,100% 100%;
  animation:psPearlDrift 7s ease-in-out infinite}
/* Secondary halves recede in plain translucent white, not colour. */
html.data-neutral .split-rest{background:rgba(255,255,255,0.14)}
html.data-neutral .dir-half.in .dir-fill{background:rgba(255,255,255,0.30)}
html.data-neutral .dir-tag.stop,html.data-neutral .dir-tag.hub{color:var(--text)}
/* Sankey footer legend swatches follow the ribbons. */
html.data-neutral .snk-foot i::before{
  background:var(--pearl-hi),var(--pearl-iri),var(--pearl-base);
  background-size:100% 100%,240% 240%,100% 100%}
html.data-neutral .snk-foot i.drop::before{background:rgba(255,255,255,0.28)}
/* Section-title KPI dot: a tiny pearl with the violet halo (a white glow on the
   dark bg reads as blur, not light — same reason spark heads glow violet). */
html.data-neutral .sec-title::before{
  background:var(--pearl-hi),var(--pearl-iri),var(--pearl-base);
  background-size:100% 100%,240% 240%,100% 100%;
  box-shadow:0 0 8px rgba(167,139,250,0.8)}
@media(prefers-reduced-motion:reduce){
  html.data-neutral .pill.pos,html.data-neutral .pill.neg,
  html.data-neutral .bk-row-bar-fill,html.data-neutral .rank-bar-fill,
  html.data-neutral .split-lead,html.data-neutral .dir-half.on .dir-fill{animation:none}
}
