/* Why Stellar index and the ten comparison articles (pages-c, 2026-10-21).
   Loaded after /_home/rework.css, which supplies the tokens, header, footer, buttons and .final3.
   Same language as the home page: Inter at 400-500, near-black, white and greys, 1px hairlines, no cards. */

/* ---------- hero (both page types) ---------- */
.ws-hero{padding:96px 0 0;text-align:center}
.ws-hero .wrap{display:flex;flex-direction:column;align-items:center}
.ws-label{font:500 14px/1.2 var(--font);color:var(--muted)}
.ws-hero h1{margin-top:18px;max-width:960px;font:400 clamp(38px,4.8vw,62px)/1.08 var(--font-h);letter-spacing:-.035em;color:var(--ink);text-wrap:balance}
.ws-hero-idx h1{max-width:1000px;font-size:clamp(42px,5.6vw,76px);line-height:1.06;letter-spacing:-.04em}
.ws-hero h1 .sw{position:relative;display:inline-block;padding-bottom:.1em}
.ws-hero h1 .sw::after{content:"";position:absolute;inset:auto 0 0;height:.2em;background:var(--green);pointer-events:none;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 14' preserveAspectRatio='none'%3E%3Cpath d='M3 10.5C42 5.5 98 3.2 197 5.6' fill='none' stroke='black' stroke-width='3.4' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") center/100% 100% no-repeat}
.ws-dek{margin-top:24px;max-width:680px;font:400 19px/1.6 var(--font);color:var(--text);text-wrap:pretty}
.ws-back{display:inline-flex;align-items:center;gap:8px;margin-bottom:40px;font:500 15px/1.2 var(--font);color:var(--muted);border-radius:var(--radius-0)}
.ws-back svg{width:16px;height:16px;transform:rotate(180deg);transition:transform var(--dur-1) var(--ease),translate var(--dur-1) var(--ease),scale var(--dur-1) var(--ease),rotate var(--dur-1) var(--ease)}
.ws-back:hover{color:var(--ink)}
.ws-back:focus-visible{outline:2px solid var(--green);outline-offset:4px;border-radius:var(--radius-0)}
.ws-back:hover svg{translate:-3px 0}
.ws-facts{display:flex;flex-wrap:wrap;justify-content:center;margin-top:32px;font:400 14.5px/1.4 var(--font);color:var(--muted)}
.ws-facts span+span::before{content:"·";margin:0 12px;color:var(--line-2)}

/* text helpers */
.hl{font-weight:500;color:var(--ink)}

/* ---------- comparison article ---------- */
.ws-article{width:100%;max-width:768px;margin:0 auto;padding:72px 32px 0}
.ws-sec{padding:0}
.ws-sec+.ws-sec,.ws-fig+.ws-sec{margin-top:72px}
.ws-sec h2{font:500 clamp(26px,2.6vw,32px)/1.2 var(--font-h);letter-spacing:-.025em;color:var(--ink);margin-bottom:20px;text-wrap:balance}
.ws-sec p{font:400 17.5px/1.75 var(--font);color:var(--text)}
.ws-sec p+p,.ws-list+p,.ws-sec .say+p{margin-top:18px}
.ws-sec .say{margin:32px 0;font:400 clamp(21px,2.1vw,25px)/1.4 var(--font-h);letter-spacing:-.018em;color:var(--ink);text-wrap:pretty}
.ws-sec .say:first-child{margin-top:0}
.ws-sec .say:last-child{margin-bottom:0}
.ws-sec .say+.say{margin-top:-12px}
.ws-sec>:first-child:not(h2){margin-top:0}
/* lists: plain rows on hairlines, like the rows of the home comparison table; nothing in front of the items */
.ws-list{list-style:none;margin:20px 0 0;padding:0;border-bottom:1px solid var(--line)}
.ws-list.two{display:grid;grid-template-columns:1fr 1fr;column-gap:32px}
.ws-list li{padding:13px 0;border-top:1px solid var(--line);font:500 16px/1.45 var(--font);color:var(--ink)}
.ws-list+.say{margin-top:32px}
.ws-list:last-child{margin-bottom:0}
/* screenshots: wider than the text, hairline frame, plain caption */
.ws-fig{margin:72px -96px 0;padding:0}
.ws-fig img{width:100%;height:auto;border-radius:var(--radius-l);border:1px solid var(--line);background:var(--sheet);box-shadow:var(--shadow-rest)}
.ws-fig figcaption{margin:14px 96px 0;font:400 14.5px/1.55 var(--font);color:var(--muted)}
.ws-fig+.ws-fig{margin-top:48px}
/* closing verdict: no card, a single line above it, then two buttons */
.ws-final{margin-top:96px!important;padding-top:56px;border-top:1px solid var(--line)}
.ws-final h2{font-size:clamp(30px,3.4vw,44px);font-weight:400;letter-spacing:-.032em;line-height:1.1;margin-bottom:24px}
.ws-ctas{display:flex;flex-wrap:wrap;gap:12px;margin-top:40px}
.ws-ctas .btn{height:52px;padding:0 24px}
body.ws main{padding-bottom:112px}

/* ---------- index ---------- */
.ws-core{padding:112px 0 0}
.ws-split{display:grid;grid-template-columns:.9fr 1.1fr;gap:64px;align-items:start;padding-top:56px;position:relative}
/* the hairline spans the content column, not the padded wrap */
.ws-split::before{content:"";position:absolute;top:0;left:32px;right:32px;border-top:1px solid var(--line)}
@media (max-width:720px){.ws-split::before{left:20px;right:20px}}
.ws-split .h2{margin-top:0}
.ws-split p{font:400 18px/1.7 var(--font);color:var(--text)}
.ws-split p+p{margin-top:18px}
.ws-group{padding:112px 0 0}
.ws-ghead{max-width:820px}
.ws-ghead .h2{margin-top:0}
.ws-ghead .lead{max-width:760px}
/* the competitor list: framed like the home comparison table, one hairline row per platform */
.ws-rows{list-style:none;margin:40px 0 0;padding:0;border:1px solid var(--line);border-radius:var(--radius-0);overflow:hidden;background:var(--sheet)}
.ws-rows li+li{border-top:1px solid var(--line)}
.ws-row{display:grid;grid-template-columns:minmax(220px,320px) 1fr 20px;gap:32px;align-items:center;padding:22px 28px;transition:background-color var(--dur-1) var(--ease)}
.ws-row:hover{background:var(--soft)}
.ws-row:focus-visible{outline:2px solid var(--green);outline-offset:-3px;border-radius:var(--radius-0)}
.ws-name b{display:block;font:500 19px/1.3 var(--font-h);letter-spacing:-.012em;color:var(--ink)}
.ws-name span{display:block;margin-top:4px;font:400 14px/1.3 var(--font);color:var(--muted)}
.ws-sum{font:400 16px/1.6 var(--font);color:var(--text)}
.ws-row>svg{width:18px;height:18px;color:var(--muted);transition:translate var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.ws-row:hover>svg{translate:3px 0;color:var(--ink)}
.ws-row:hover .ws-name b{text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:1px}
.ws-one{padding:128px 0 32px}
.ws-motto{margin-top:28px;font:500 19px/1.4 var(--font);color:var(--ink);text-wrap:balance}
/* prop-audit 2026-10-23: the closing band keeps its 96px bottom padding (padding-bottom:0 clipped the headline at the footer) */

/* ---------- responsive ---------- */
@media (max-width:1000px){
  .ws-fig{margin-left:0;margin-right:0}
  .ws-fig figcaption{margin-left:0;margin-right:0}
}
@media (max-width:899px){
  .ws-split{grid-template-columns:1fr;gap:24px}
  .ws-row{grid-template-columns:1fr 18px;gap:8px 20px;padding:20px 22px}
  .ws-name{grid-column:1}
  .ws-sum{grid-column:1;grid-row:2}
  .ws-row>svg{grid-column:2;grid-row:1 / span 2}
}
@media (max-width:720px){
  .ws-hero{padding-top:48px}
  .ws-hero h1{font-size:clamp(32px,8.6vw,40px);line-height:1.14;letter-spacing:-.03em}
  .ws-hero-idx h1{font-size:clamp(34px,9.8vw,44px);line-height:1.12}
  .ws-dek{font-size:17px;line-height:1.65}
  .ws-back{margin-bottom:28px}
  .ws-facts{margin-top:24px;row-gap:4px}
  /* the comparison name takes its own line so no "·" is left dangling at a line start */
  .ws-facts span:first-child{flex-basis:100%}
  .ws-facts span:nth-child(2)::before{content:none}
  .ws-article{padding:52px 20px 0}
  .ws-sec+.ws-sec,.ws-fig+.ws-sec{margin-top:56px}
  .ws-sec p{font-size:16.5px;line-height:1.7}
  .ws-list.two{grid-template-columns:1fr}
  .ws-fig{margin-top:52px}
  .ws-final{margin-top:72px!important;padding-top:44px}
  .ws-ctas .btn{flex:1 1 100%}
  body.ws main{padding-bottom:72px}
  .ws-core,.ws-group{padding-top:80px}
  .ws-split{padding-top:40px}
  .ws-split p{font-size:17px}
  .ws-rows{margin-top:28px}
  .ws-one{padding:96px 0 16px}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .ws-row,.ws-row>svg,.ws-back svg{transition:none}
  .ws-row:hover>svg{transform:none;translate:none;scale:none;rotate:none}
  .ws-back:hover svg{translate:none}
}

/* green hint (owner 2026-10-21): the underline above follows the theme, plus green arrows on the small "go" links */
.ws-row>svg,.ws-row:hover>svg,.ws-back svg{color:var(--green)}

/* wave mktC (2026-10-22): checked against the home page */
/* left-aligned article headings: fill the line and only avoid a lone last word ("balance" made two short ragged lines) */
.ws-sec h2,.ws-final h2{text-wrap:pretty}
/* the caption starts at the screenshot's left edge, as the home mock-up captions do */
@media (min-width:1001px){.ws-fig figcaption{margin:14px 2px 0}}
@media (max-width:720px){
  /* closing buttons fill the line, like the home closing section on mobile (R23) */
  .ws-ctas .btn{flex:1 1 auto;justify-content:center}
}
/* bug hunt (bh-home): sections sit on their own bands now (marketing-shell.css), so each gets padding at both ends,
   the hairline over the core split goes (the band change separates it), and the competitor frame takes the card
   radius like every other card */
.ws-hero{padding-bottom:96px}
.ws-core,.ws-group{padding:96px 0}
.ws-one{padding:112px 0}
body.ws main{padding-bottom:0}
.ws-split{padding-top:0}
.ws-split::before{content:none}
.ws-rows{border-radius:var(--radius-l)}
@media (max-width:720px){.ws-hero{padding-bottom:56px}.ws-core,.ws-group{padding:64px 0}.ws-one{padding:72px 0}}

/* repropagation 2026-10-22 evening (notes/prop-marketing.md): comparison articles as full-width neutral bands
   (.sx-band, set by tools/gen_why_stellar.py) with a centred reading column; screenshots are white pop-out sheets on a
   bleed panel with a Fig. caption. */
.ws-article{max-width:none;margin:0;padding:0}
.ws-article>.ws-sec{margin-top:0!important}
.ws-reading{max-width:704px;margin-inline:auto}
.ws-media{margin-top:56px}
.ws-media .ws-fig{margin:0 auto;max-width:880px}
.ws-media .ws-fig+.ws-fig{margin-top:48px}
.ws-sheet{overflow:hidden}
.ws-sheet img{display:block;width:100%;height:auto;border:0;border-radius:0;box-shadow:none;background:none}
.ws-fig.sx-fig>figcaption{margin:18px 0 0;font:500 15px/1.4 var(--font);color:var(--ink)}
.ws-final{margin-top:0!important;border-top:0}
@media (max-width:720px){.ws-media{margin-top:40px}.ws-fig.sx-fig>figcaption{margin:16px 0 0;font-size:14.5px}}

/* Phones (swarm R4): the underlined phrase wraps, and an inline-block then fills the whole line, leaving "A" alone on its own line
   and an underline wider than the words. Inline with a cloned background puts one stroke under each line of the phrase. */
@media (max-width:720px){
  .ws-hero h1 .sw{display:inline;padding-bottom:.08em;-webkit-box-decoration-break:clone;box-decoration-break:clone;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 14' preserveAspectRatio='none'%3E%3Cpath d='M3 10.5C42 5.5 98 3.2 197 5.6' fill='none' stroke='%2313863f' stroke-width='3.4' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") left bottom/100% .2em no-repeat}
  html.dark .ws-hero h1 .sw{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 14' preserveAspectRatio='none'%3E%3Cpath d='M3 10.5C42 5.5 98 3.2 197 5.6' fill='none' stroke='%233fb26b' stroke-width='3.4' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E")}
  .ws-hero h1 .sw::after{content:none}
}

/* swarm R12 home-marketing: the hero underline crossed the "g" in "learning". A halo in the hero paper colour,
   painted under the letters, breaks the line around descenders (like skip-ink) without moving it. */
.ws-hero h1 .sw{isolation:isolate;-webkit-text-stroke:.07em var(--band-paper,#f8f8f6);paint-order:stroke fill}
.ws-hero h1 .sw::after{z-index:-1}

/* swarm R15/R27 home-marketing: "Back to Why Stellar" has a 28px hit area across all viewports. Same position, taller hit area. */
.ws-back{padding-block:5px;margin-top:-5px;margin-bottom:35px}
@media (max-width:1024px){.ws-back{margin-bottom:23px}}

/* swarm R17 home-marketing: the "One system" quote block draws its half-width hairlines (.sx-quote-rule) on its own
   box, which had no padding, so the top rule touched the H2 caps and the bottom rule read as an underline of the motto.
   Give the rules room, like the home page quote. */
.ws-one .sx-quote-rule{padding:40px 0 44px}
@media (max-width:720px){.ws-one .sx-quote-rule{padding:32px 0 34px}}

/* swarm R28 home-marketing-why:
   1. On mobile (<=720px), .ws-facts wraps onto two lines with a leading "·" dot stranded at the start of line 2.
      Place the comparison title on its own line and "N min read · Info guide" below it with no stranded dot.
   2. .ws-list had a solid bottom border on the <ul> while <li> rows use dashed top rules, spanning across the 32px
      column gap in .ws-list.two and leaving odd-count right-column items unclosed above an empty bordered cell.
      Move the bottom dashed rule onto each <li> cell so every item closes its own column and matches the dashed rules. */
@media (max-width:720px){
  .ws-facts{row-gap:4px}
  .ws-facts span:first-child{flex-basis:100%}
  .ws-facts span:nth-child(2)::before{content:none}
}
.ws-list{border-bottom:0}
.ws-list li{border-top:0;border-bottom:1px dashed var(--rule-dash)}
.ws-list li:first-child{border-top:1px dashed var(--rule-dash)}
@media (min-width:721px){
  .ws-list.two li:nth-child(2){border-top:1px dashed var(--rule-dash)}
}

/* swarm R28 home-marketing-why: keep FIG. N beside multi-line captions (at weight 500), and close each column of a
   two-column list under its own last item so odd-length lists do not leave an unbordered empty cell on the right. */
.ws-fig.sx-fig>figcaption{align-items:baseline}
.ws-fig.sx-fig>figcaption::before{font-weight:500}
.ws-fig.sx-fig>figcaption>span{flex:1 1 0;min-width:0}
@media (min-width:721px){
  .ws-list.two{border-bottom:0}
  .ws-list.two li:last-child,
  .ws-list.two li:nth-last-child(2):nth-child(odd){border-bottom:1px solid var(--line)}
  .ws-list.two li:nth-last-child(2):nth-child(even){box-shadow:0 1px 0 var(--line)}
}

/* swarm R29 home-marketing-why: the two-column lists closed their last row with a solid rule (and, on odd lists,
   a solid shadow under the dashed rule, so two lines), while every other row is dashed. One dashed rule per row,
   like the home comparison table. The "Fig. N" label goes back to the home page's 600 (rework.css .try>span::before). */
@media (min-width:721px){
  .ws-list.two li:last-child,
  .ws-list.two li:nth-last-child(2):nth-child(odd){border-bottom:1px dashed var(--rule-dash)}
  .ws-list.two li:nth-last-child(2):nth-child(even){box-shadow:none}
}
.ws-fig.sx-fig>figcaption::before{font-weight:600}

/* swarm R30 home-marketing-why: "Back to Why Stellar" was a 28px tap target (44px is the floor). Grow the hit box to 44px
   with padding and take the same amount back in negative margins, so the text and the hero spacing stay put. The focus
   ring now hugs the padded box with the 10px nav-item corner instead of floating 4px outside a squared box. */
.ws-back{padding:13px 12px;margin:-13px -12px 27px;border-radius:var(--radius-m,10px)}
.ws-back:focus-visible{outline-offset:0;border-radius:var(--radius-m,10px)}
@media (max-width:1024px){.ws-back{margin-bottom:15px}}

/* swarm R31 home-marketing-why:
   1. Index hero: the hand-drawn underline ran through the descenders of "g" and "p" in "free learning platform"
      at every width. Drop the stroke below the descenders and open the line height just enough that it does not
      touch the next line's ascenders (the comparison pages underline "Stellar"/"Both", no descenders, untouched).
   2. Comparison rows under 900px: the arrow kept its own column beside the summary, so the summary wrapped in a
      narrow column (rows 197px tall on phones). The arrow now sits on the name line and the summary runs full width. */
@media (min-width:721px){
  .ws-hero-idx h1{line-height:1.15}
  .ws-hero-idx h1 .sw::after{bottom:-.11em}
}
@media (max-width:720px){
  .ws-hero-idx h1{line-height:1.17}
  .ws-hero-idx h1 .sw{padding-bottom:.17em}
}
@media (max-width:899px){
  .ws-row{column-gap:16px}
  .ws-name{grid-row:1}
  .ws-sum{grid-column:1 / -1}
  .ws-row>svg{grid-row:1;align-self:start;margin-top:4px}
}

/* swarm R34 home-marketing-why:
   1. Screenshot lightbox dialog: .ws-zoom interactive trigger on comparison screenshots,
      .ws-lb dialog modal with dark/light backdrops, 44px close button, caption bar,
      and pan container for full-resolution inspection.
   2. Mobile symmetrical bleed: on <=720px, normalize .ws-media.sx-panel-bleed to bleed
      symmetrically across both edges, eliminating the 21px zigzag offset between
      alternating left and right bleed panels. */
.ws-zoom{
  cursor:zoom-in;
  position:relative;
  transition:translate var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease);
}
.ws-zoom:hover{
  translate:0 var(--lift);
  box-shadow:var(--shadow-float);
}
.ws-zoom:focus-visible{outline:2px solid var(--green);outline-offset:2px;border-radius:var(--radius-l)}

/* swarm R35 home-marketing-why:
   1. Screenshot zoom affordance badge: subtle 32px pill badge indicating expandable view for touch and desktop.
   2. Lightbox caption text-wrap: prevent mobile ellipsis truncation of explanatory figure captions.
   3. Keyboard pan focus: provide visible green ring on .ws-lb-pan when navigated with Tab.
   4. Comparison rows corner radii: match container 16px corners on first and last row focus rings. */
.ws-rows li:first-child .ws-row{border-top-left-radius:var(--radius-l);border-top-right-radius:var(--radius-l)}
.ws-rows li:last-child .ws-row{border-bottom-left-radius:var(--radius-l);border-bottom-right-radius:var(--radius-l)}

.ws-zoom::after{
  content:"";
  position:absolute;
  right:14px;
  bottom:14px;
  width:32px;
  height:32px;
  border-radius:var(--radius-pill);
  background:var(--sheet);
  border:1px solid var(--line);
  box-shadow:var(--shadow-rest);
  opacity:.88;
  pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23121614' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='6.5'/%3E%3Cline x1='21' y1='21' x2='15.65' y2='15.65'/%3E%3Cline x1='11' y1='8' x2='11' y2='14'/%3E%3Cline x1='8' y1='11' x2='14' y2='11'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:center;
  background-size:16px 16px;
  transition:opacity var(--dur-1) var(--ease),scale var(--dur-1) var(--ease);
}
html.dark .ws-zoom::after{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f8f8f6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='6.5'/%3E%3Cline x1='21' y1='21' x2='15.65' y2='15.65'/%3E%3Cline x1='8' y1='11' x2='14' y2='11'/%3E%3C/svg%3E");
}
.ws-zoom:hover::after{
  opacity:1;
  scale:1.06;
}

html.ws-lb-open,html.ws-lb-open body{overflow:hidden}
/* R50 (owner 19:40, "the scrollbar disappears" when a pop-up opens): on desktops the scrollbar stays put while the
   lightbox is open, so the page behind no longer jumps sideways. why.js stops wheel scrolling behind the dialog. */
@media (hover:hover) and (pointer:fine){
  html.ws-lb-open{overflow-y:scroll;scrollbar-gutter:stable}
  html.ws-lb-open body{overflow:visible}
}

dialog.ws-lb{
  position:fixed;
  inset:0;
  margin:auto;
  width:calc(100vw - 48px);
  max-width:1240px;
  max-height:calc(100vh - 48px);
  padding:0;
  border:1px solid var(--line);
  border-radius:var(--radius-l);
  background:var(--sheet);
  box-shadow:var(--shadow-float);
  color:var(--ink);
  overflow:hidden;
  outline:0;
  z-index:9000;
}
dialog.ws-lb:not([open]){display:none}
dialog.ws-lb[open]{
  display:flex;
  flex-direction:column;
  animation:sx-pop var(--dur-2) var(--ease) both;
}
dialog.ws-lb::backdrop{
  background:rgba(18,22,20,.45);
  backdrop-filter:blur(2px);
  -webkit-backdrop-filter:blur(2px);
  animation:sx-fade var(--dur-2) var(--ease) both;
}
html.dark dialog.ws-lb::backdrop{
  background:rgba(0,0,0,.65);
}

.ws-lb-bar{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:16px;
  padding:12px 18px;
  border-bottom:1px solid var(--line);
  background:var(--sheet);
  flex-shrink:0;
}
.ws-lb-cap{
  font:500 14px/1.4 var(--font);
  color:var(--ink);
  text-wrap:pretty;
  word-break:break-word;
}
.ws-lb-actions{
  display:flex;
  align-items:center;
  gap:8px;
  flex-shrink:0;
}
.ws-lb-nav{
  display:inline-flex;
  align-items:center;
  gap:4px;
}
.ws-lb-btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:44px;
  height:44px;
  min-width:44px;
  min-height:44px;
  padding:0;
  border:1px solid var(--line);
  border-radius:var(--radius-m,10px);
  background:var(--sheet);
  color:var(--ink);
  cursor:pointer;
  flex-shrink:0;
  transition:background-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease),opacity var(--dur-1) var(--ease);
}
.ws-lb-btn:hover:not(:disabled){
  background:var(--soft);
  color:var(--ink);
  border-color:var(--line-2);
}
.ws-lb-btn:disabled{
  opacity:.32;
  cursor:not-allowed;
}
.ws-lb-btn:focus-visible{
  outline:2px solid var(--green);
  outline-offset:1px;
}
.ws-lb-btn svg{
  width:16px;
  height:16px;
}
.ws-lb-count{
  font:500 13px/1 var(--font);
  color:var(--muted);
  font-variant-numeric:tabular-nums;
  padding:0 6px;
  white-space:nowrap;
}
.ws-lb-zoom{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  height:44px;
  min-width:44px;
  padding:0 14px;
  border:1px solid var(--line);
  border-radius:var(--radius-m,10px);
  background:var(--sheet);
  color:var(--ink);
  font:600 13px/1 var(--font);
  letter-spacing:.01em;
  cursor:pointer;
  flex-shrink:0;
  transition:background-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease);
}
.ws-lb-zoom:hover{
  background:var(--soft);
  border-color:var(--line-2);
}
.ws-lb-zoom:focus-visible{
  outline:2px solid var(--green);
  outline-offset:1px;
}
.ws-lb-x{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:2px;
  height:44px;
  min-width:44px;
  min-height:44px;
  padding:0 12px;
  border:1px solid var(--line);
  border-radius:var(--radius-m,10px);
  background:var(--sheet);
  color:var(--muted);
  cursor:pointer;
  flex-shrink:0;
  transition:background-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease);
}
.ws-lb-x:hover{
  background:var(--soft);
  color:var(--ink);
  border-color:var(--line-2);
}
.ws-lb-x:focus-visible{
  outline:2px solid var(--green);
  outline-offset:1px;
}
.ws-lb-x svg{
  width:18px;
  height:18px;
}

.ws-lb-pan{
  flex:1 1 auto;
  min-height:0;
  overflow:auto;
  overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  padding:20px;
  background:var(--soft);
  display:flex;
  outline:0;
}
.ws-lb-pan:focus-visible{
  outline:2px solid var(--green);
  outline-offset:-2px;
}
.ws-lb-pan img{
  display:block;
  max-width:100%;
  max-height:calc(85vh - 110px);
  width:auto;
  height:auto;
  margin:auto;
  border-radius:var(--radius-m,10px);
  border:1px solid var(--line);
  box-shadow:var(--shadow-rest);
  background:var(--sheet);
  cursor:zoom-in;
}
.ws-lb-pan.is-zoomed img{
  max-width:none;
  max-height:none;
  width:auto;
  height:auto;
  cursor:zoom-out;
}

.ws-lb-hint{
  display:none;
}

@media (max-width:720px){
  .ws-media.sx-panel-bleed,
  .ws-media.sx-panel-bleed--left{
    margin-left:calc(-1 * var(--wrap-pad));
    margin-right:calc(-1 * var(--wrap-pad));
    padding-left:var(--wrap-pad);
    padding-right:var(--wrap-pad);
    border-left:0;
    border-right:0;
    border-radius:0;
  }
  dialog.ws-lb{
    width:calc(100vw - 20px);
    max-height:calc(100dvh - 32px);
    border-radius:var(--radius-l,16px);
  }
  /* R49: caption gets its own full-width row; it was squeezed to ~50px and broke mid-word at 375 */
  .ws-lb-bar{
    flex-wrap:wrap;
    padding:12px 14px;
    gap:10px 12px;
  }
  .ws-lb-cap{flex:1 1 100%}
  .ws-lb-actions{flex:1 1 100%}
  .ws-lb-zoom{margin-left:auto}
  .ws-lb-pan{
    padding:12px;
  }
  .ws-lb-pan img{
    max-width:none;
    height:min(55vh,420px);
    width:auto;
  }
  .ws-lb-hint{
    display:block;
    margin:0;
    padding:8px 12px;
    font:400 12.5px/1.3 var(--font);
    color:var(--muted);
    text-align:center;
    background:var(--sheet);
    border-top:1px solid var(--line);
    flex-shrink:0;
  }
}

@media (prefers-reduced-motion:reduce){
  dialog.ws-lb[open],dialog.ws-lb::backdrop{animation:none}
  .ws-zoom,.ws-zoom::after{transition:none}
  .ws-zoom:hover{translate:none}
  .ws-zoom:hover::after{scale:none}
}

/* ---------- search and category filter (owner 21:15 standing program) ---------- */
.ws-filter-sec{padding:72px 0 0}
.ws-filter-head{max-width:820px;margin-bottom:28px}
.ws-filter-head .h2{margin-top:0}
.ws-tools{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:16px 24px;margin-bottom:12px}
.ws-search-wrap{position:relative;flex:1 1 320px;max-width:440px;min-width:0}
.ws-search-mag{position:absolute;left:14px;top:13px;width:18px;height:18px;color:var(--muted);pointer-events:none}
.ws-search-input{width:100%;height:44px;padding:0 76px 0 42px;border:1px solid var(--line-2);border-radius:var(--radius-m,10px);background:var(--sheet);font:400 15px/1 var(--font);color:var(--ink);outline:0;-webkit-appearance:none;appearance:none;transition:border-color var(--dur-1) var(--ease),box-shadow var(--dur-1) var(--ease)}
.ws-search-input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none;display:none}
.ws-search-input::placeholder{color:var(--muted)}
.ws-search-input:hover{border-color:var(--muted)}
.ws-search-input:focus-visible,.ws-search-input:focus{border-color:var(--green);outline:2px solid var(--green);outline-offset:2px}
.ws-search-wrap:focus-within .ws-slash-hint{opacity:0;pointer-events:none}
.ws-clear-x{position:absolute;right:2px;top:0;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;min-width:44px;min-height:44px;padding:0;border:0;border-radius:var(--radius-m,10px);background:transparent;color:var(--muted);cursor:pointer;transition:color var(--dur-1) var(--ease)}
.ws-clear-x:hover{color:var(--ink)}
.ws-clear-x:focus-visible{outline:2px solid var(--green);outline-offset:1px}
.ws-clear-x svg{width:16px;height:16px}
.ws-slash-hint{position:absolute;right:12px;top:12px;display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;padding:0 5px;border:1px solid var(--line);border-radius:6px;background:var(--soft);color:var(--muted);font:500 12px/1 var(--font);pointer-events:none;transition:opacity var(--dur-1) var(--ease)}
.ws-chips{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.ws-chip{display:inline-flex;align-items:center;gap:8px;height:44px;min-height:44px;padding:0 16px;border:1px solid var(--line-2);border-radius:var(--radius-pill);background:var(--sheet);font:500 14.5px/1 var(--font);color:var(--ink);cursor:pointer;transition:background-color var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.ws-chip .ws-count{font-weight:400;color:var(--muted);font-variant-numeric:tabular-nums}
.ws-chip:hover{border-color:var(--ink)}
.ws-chip.is-active{background:var(--ink);border-color:var(--ink);color:var(--sheet)}
.ws-chip.is-active .ws-count{color:inherit;opacity:.72}
.ws-chip:focus-visible{outline:2px solid var(--green);outline-offset:2px}
.ws-chip:active{scale:.98}
.ws-status-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:4px 0 0;font:400 14px/1.4 var(--font);color:var(--muted);min-height:36px}
.ws-status-main{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.ws-active-pills{display:inline-flex;flex-wrap:wrap;align-items:center;gap:6px}
.ws-pill{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:var(--radius-pill);background:var(--soft);border:1px solid var(--line);font:500 12.5px/1.3 var(--font);color:var(--ink)}
.ws-pill-x{position:relative;display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;margin-left:2px;border:0;border-radius:50%;background:transparent;color:var(--muted);cursor:pointer;transition:background-color var(--dur-1) var(--ease),color var(--dur-1) var(--ease)}
.ws-pill-x:hover{color:var(--ink);background:var(--line)}
.ws-pill-x:focus-visible{outline:2px solid var(--green);outline-offset:1px}
.ws-pill-x svg{width:11px;height:11px}
/* R49: the 18px remove button keeps its look but gets a 38px invisible hit area */
.ws-pill-x::after{content:"";position:absolute;inset:-10px}
.ws-pill{font-size:13px;padding:4px 8px 4px 12px}
.ws-reset-link{display:inline-flex;align-items:center;min-height:44px;padding:0 6px;background:none;border:0;font:500 14px/1.4 var(--font);color:var(--green);cursor:pointer;text-decoration:underline;text-underline-offset:3px}
.ws-reset-link:hover{color:var(--ink)}
.ws-reset-link:focus-visible{outline:2px solid var(--green);outline-offset:2px;border-radius:4px}
.ws-row mark,.ws-mark{background:rgba(30,107,74,.18);color:inherit;padding:0 3px;border-radius:3px;font-weight:600}
html.dark .ws-row mark,html.dark .ws-mark{background:rgba(82,184,122,.32);color:inherit}
.ws-empty{margin-top:32px}
.ws-empty-card{padding:48px 24px;text-align:center;border-radius:var(--radius-l);display:flex;flex-direction:column;align-items:center;background:var(--sheet);border:1px solid var(--line);box-shadow:var(--shadow-rest)}
.ws-empty-icon{width:40px;height:40px;color:var(--muted);margin-bottom:16px}
.ws-empty-heading{font:500 20px/1.3 var(--font-h);color:var(--ink);margin:0 0 8px}
.ws-empty-msg{font:400 15px/1.6 var(--font);color:var(--muted);max-width:440px;margin:0 0 24px}
/* R50: suggested searches in the empty state, the same hairline pills as the filter chips */
.ws-empty-msg:has(+.ws-suggest){margin-bottom:14px}
.ws-suggest{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin:0 0 24px}
.ws-suggest-btn{display:inline-flex;align-items:center;height:44px;padding:0 16px;border:1px solid var(--line-2);border-radius:var(--radius-pill);background:var(--sheet);font:500 14px/1 var(--font);color:var(--ink);cursor:pointer;transition:border-color var(--dur-1) var(--ease),translate var(--dur-2,240ms) var(--ease)}
.ws-suggest-btn:hover{border-color:var(--ink);translate:0 -1px}
.ws-suggest-btn:active{scale:.98}
.ws-suggest-btn:focus-visible{outline:2px solid var(--green);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.ws-suggest-btn{transition:none}.ws-suggest-btn:hover{translate:none}}
.ws-group[hidden]{display:none}
.ws-reset-link[hidden],.ws-clear-x[hidden],.ws-active-pills[hidden]{display:none}
.ws-search-wrap:has(.ws-clear-x:not([hidden])) .ws-slash-hint{display:none}
.ws-rows li[hidden]{display:none}

.ws-lb-zoom .ws-kbd,.ws-lb-x .ws-kbd{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-width:20px;
  height:20px;
  padding:0 5px;
  margin-left:6px;
  border:1px solid var(--line);
  border-radius:6px;
  background:var(--soft);
  color:var(--muted);
  font:500 11px/1 var(--font);
}

@media (max-width:720px){
  .ws-filter-sec{padding:48px 0 0}
  .ws-tools{flex-direction:column;align-items:stretch;gap:14px}
  .ws-search-wrap{flex:none;max-width:none}
  .ws-chips{gap:8px}
  .ws-chip{height:44px;padding:0 14px;font-size:14px}
  .ws-empty-card{padding:36px 16px}
  /* R49: "/" hint is pointless on narrow screens and it truncated the placeholder at 375 */
  .ws-slash-hint{display:none}
  .ws-search-input{padding-right:44px}
  .ws-reset-link{padding:0}
  /* R50: 16px text so iPhones do not zoom the page when the field is tapped */
  .ws-search-input{font-size:16px}
}
/* R49: four chips fell into three ragged rows at 375; an even 2 x 2 grid instead */
@media (max-width:520px){
  .ws-chips{display:grid;grid-template-columns:1fr 1fr}
  .ws-chip{justify-content:center;padding:0 10px;white-space:nowrap}
}
@media (max-width:560px),(pointer:coarse){
  .ws-lb-zoom .ws-kbd,.ws-lb-x .ws-kbd{display:none}
}
@media (pointer:coarse){
  .ws-slash-hint{display:none}
  .ws-search-input{padding-right:44px;font-size:16px}
}
/* swarm R51 home-marketing: with the "/" hint hidden, an empty field has no clear button either, so the placeholder
   gets the 44px back (it was cut to "Search by platform or keywo" at 360). Narrower phones end it in an ellipsis */
.ws-search-input{text-overflow:ellipsis}
@media (max-width:720px),(pointer:coarse){
  .ws-search-input:placeholder-shown{padding-right:14px}
}
@media (prefers-reduced-motion:reduce){
  .ws-search-input,.ws-chip,.ws-clear-x,.ws-slash-hint{transition:none}
}
/* swarm R55 home-marketing-why: the 25px pull lines in the articles left a short tail alone on line 2 at desktop
   widths ("for mastery.", "exam-oriented.", "for the AP exam."). Balance them, like the motto (R52). */
.ws-sec .say{text-wrap:balance}
/* hyphenated words in a pull line stay whole ("recall-/oriented" broke at the hyphen once balanced) */
.ws-nw{white-space:nowrap}
