/* ==========================================================================
   BrainTrivia listing layout — homepage + browse page ONLY.
   Modelled on braintrivia.net's own structure: two-column shell with a right
   rail, hero + stat trio, "Popular this week", per-category sections, flat
   cards with a format badge and a meta footer.

   Quiz gameplay pages do not load this file — they keep the MixGames UI.
   All colour comes from the tokens in bt-theme.css.
   ========================================================================== */

/* The box-sizing reset these pages were missing now lives in bt-chrome.css —
   it is the only stylesheet every page loads, and the footer sits outside
   .bt-shell so scoping it here was not enough. */
.bt-shell{max-width:1180px;margin:0 auto;padding:22px 24px 0;display:flex;gap:26px;align-items:flex-start}
.bt-main{flex:1 1 auto;min-width:0}
/* 308, up from 286 — the extra room the tiles wanted, now applied to all three
   equally rather than one of them overflowing into it. */
.bt-rail{flex:0 0 308px;width:308px;position:sticky;top:79px}

/* hero --------------------------------------------------------------------- */
.bt-hero{display:flex;align-items:flex-start;justify-content:space-between;gap:28px;flex-wrap:wrap;margin:0 0 26px}
.bt-hero h1{
  font-family:var(--font-display);font-size:34px;line-height:1.18;letter-spacing:-.6px;
  font-weight:700;color:var(--ink);margin:0 0 10px;max-width:22ch;
}
.bt-hero p{color:var(--muted);font-size:14.5px;line-height:1.55;margin:0;max-width:56ch}
.bt-stats{display:flex;gap:26px;flex:0 0 auto;padding-top:4px}
.bt-stat b{display:block;font-family:var(--font-display);font-size:23px;font-weight:700;color:var(--ink);letter-spacing:-.4px}
.bt-stat span{display:block;font-size:12px;color:var(--muted);margin-top:1px}

/* section headers ---------------------------------------------------------- */
.bt-sec{margin:0 0 30px}
.bt-sec-h{display:flex;align-items:center;gap:11px;margin:0 0 14px}
/* Icons are Material Symbols Rounded outlines (see partials/bt-icons.json) —
   the family braintrivia.net uses. They inherit currentColor, so each sits in
   its category's own foreground on its own tint. Emoji couldn't do that: they
   render differently on every OS and ignore colour entirely. */
.bt-sec-ico{
  width:36px;height:36px;border-radius:10px;flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;
  background:var(--cbg,var(--primtint));color:var(--cfg,var(--primaryd));
}
.bt-sec-ico svg{width:21px;height:21px;display:block}
.bt-all svg{width:17px;height:17px;margin-right:-4px}
.bt-trend{display:inline-flex;color:#f08a24}   /* matches braintrivia.net's trending mark */
.bt-trend svg{width:20px;height:20px;display:block}
.bt-sec-t{flex:1 1 auto;min-width:0}
.bt-sec-t h2{font-family:var(--font-display);font-size:18px;font-weight:700;letter-spacing:-.3px;color:var(--ink);margin:0}
.bt-sec-t p{font-size:12.5px;color:var(--muted);margin:2px 0 0}
.bt-all{
  flex:0 0 auto;font-size:13px;font-weight:600;color:var(--primary);
  text-decoration:none;display:inline-flex;align-items:center;gap:3px;
}
.bt-all:hover{text-decoration:underline}
.bt-sec-simple{display:flex;align-items:center;gap:8px;margin:0 0 14px}
.bt-sec-simple h2{font-family:var(--font-display);font-size:18px;font-weight:700;letter-spacing:-.3px;margin:0;color:var(--ink)}

/* category colour coding ----------------------------------------------------
   braintrivia.net ships 8 --cat-*-bg / --cat-*-fg token pairs. They're used
   here to colour each section's icon tile and its cards' tag chips, so the page
   reads by category at a glance instead of everything being one purple.
   Ten of our tags map onto eight pairs, so two pairs are shared (noted below).
   --------------------------------------------------------------------------- */
/* Reworked. The original eight pairs were lifted wholesale from
   braintrivia.net's cat-* tokens, but their categories are Entertainment /
   History / Sports / Arts / Personality — so mapping our ten tags onto their
   eight slots produced assignments that meant nothing. Two were actively wrong:

     Personality was #c33a28, ~15° from --noink (#a3291d), the colour the quiz
     engine uses for a WRONG ANSWER. It is also our largest category (25 of 75)
     and sections sort by size, so the alarm hue always led the page: on the
     first screen every pill, the lead section and six tinted placeholders were
     all the error red.

     Tech/IQ was #7431c7, essentially the brand purple. Category chips must not
     wear the CTA colour or "press this" stops meaning anything.

   Two rules now hold: no category uses the red family, and none uses the brand
   violet. Personality takes the calmest hue precisely because it is the most
   frequent; Geography moves to forest to vacate teal; Tech/IQ goes neutral
   slate, which suits it and stays clear of the CTA.

   Every pair is generated to clear 4.6:1 — pill text is 11px, so AA wants 4.5
   and four of the original eight missed it (Personality 4.31, Sports 4.16,
   Nostalgia 4.39, Geography 4.49). Ratios are in the comments. */
.c-pers { --cbg:#e1f1f6; --cfg:#0c7297 }   /* Personality  teal-blue  4.68 */
.c-hist { --cbg:#faebd3; --cfg:#965d08 }   /* Nostalgia    amber      4.63 */
.c-sci  { --cbg:#dbe5fd; --cfg:#1b4bbb }   /* Faith        indigo     6.01 */
.c-arts { --cbg:#fcdce9; --cfg:#b1255f }   /* Music        berry      5.02 */
.c-triv { --cbg:#e4e0fb; --cfg:#402bab }   /* Words,Trivia deep indigo 7.60 */
.c-geo  { --cbg:#ddf1e1; --cfg:#19762c }   /* Geography    forest     4.84 */
.c-sport{ --cbg:#fce6d9; --cfg:#af490e }   /* Sports       burnt or.  4.62 */
.c-ent  { --cbg:#e8ebf0; --cfg:#546583 }   /* Tech,IQ      slate      4.93 */

/* Dark counterparts. The light tints are ~92% lightness — dropped onto a
   charcoal surface they glare like little lightboxes, and the dark foregrounds
   then fail contrast against them. Each pair is inverted rather than dimmed:
   the tint becomes a deep, desaturated version of the same hue and the ink is
   lifted well above it, so the category reads at a glance in either theme. */
:root[data-theme="dark"] .c-pers { --cbg:#1c2d33; --cfg:#69b7d3 }   /* 6.33 */
:root[data-theme="dark"] .c-hist { --cbg:#352815; --cfg:#ddab5f }   /* 6.87 */
:root[data-theme="dark"] .c-sci  { --cbg:#15223f; --cfg:#6389e3 }   /* 4.67 */
:root[data-theme="dark"] .c-arts { --cbg:#3a1524; --cfg:#dd5f94 }   /* 4.68 */
:root[data-theme="dark"] .c-triv { --cbg:#1f193b; --cfg:#8d7cde }   /* 4.82 */
:root[data-theme="dark"] .c-geo  { --cbg:#1b2c1f; --cfg:#6ecf81 }   /* 7.64 */
:root[data-theme="dark"] .c-sport{ --cbg:#382114; --cfg:#e28c5a }   /* 5.83 */
:root[data-theme="dark"] .c-ent  { --cbg:#24272e; --cfg:#8b99b1 }   /* 5.19 */

/* card grid ----------------------------------------------------------------
   Browse and the featured row stay fluid (auto-fill), but the homepage section
   grids are pinned to a fixed 3-up. With auto-fill the column count changes to
   4 in the 760-1040px band, which would leave a six-card section showing a
   ragged trailing row of two. Fixed columns keep every section two clean rows
   and, as a bonus, give the cards more width for the image. */
/* Browse keeps the fluid grid. Homepage sections are pinned further down —
   see ".bt-sec .bt-grid" in the section-grid block. */
.bt-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(216px,1fr));gap:16px}
.bt-card{
  position:relative;                 /* .bt-play centres against the whole tile */
  display:flex;flex-direction:column;background:var(--card);
  border:1px solid var(--glassbrd);border-radius:12px;overflow:hidden;
  text-decoration:none;color:inherit;
  transition:border-color .16s ease,transform .16s ease;
}
.bt-card:hover{border-color:var(--primary);transform:translateY(-2px)}
.bt-card:focus-visible{outline:2px solid var(--logo);outline-offset:2px;border-color:var(--logo)}
.bt-thumb{position:relative;aspect-ratio:16/9;background:var(--cbg,var(--heroA));overflow:hidden}
.bt-thumb img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .35s ease}
.bt-card:hover .bt-thumb img{transform:scale(1.035)}
.bt-thumb .ph{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:44px}

/* hover affordance ----------------------------------------------------------
   braintrivia.net dims the thumbnail on hover and floats a "Play Now" pill over
   it. It's worth copying: the whole card is already a link, but nothing on it
   named the action, so the tile read as an article teaser rather than something
   you press. The scrim also buys the pill legible contrast over photographs we
   don't control.

   The pill centres on the WHOLE tile, not the thumbnail — it is a child of
   .bt-card. On a 16:9 thumb plus a two-line body the tile's midpoint sits low
   in the image, so the pill still lands mostly over the photo (where the scrim
   backs it) while reading as the centre of the thing you are about to click.
   The scrim deliberately stays on the thumbnail alone: the body is a light
   surface with dark text, and dimming it would render the title unreadable at
   exactly the moment the reader is deciding. Where the pill overhangs onto the
   body its own white fill and shadow carry the separation.

   Pointer-only. On touch there is no hover state to reveal it, so the pill
   would either never appear or — worse — stick after a tap and sit over the
   image while the page navigates. It is display:none outside this query.
   --------------------------------------------------------------------------- */
.bt-play{display:none}
@media (hover:hover) and (pointer:fine){
  .bt-thumb::after{
    content:"";position:absolute;inset:0;pointer-events:none;
    background:rgba(18,15,32,.44);opacity:0;transition:opacity .17s ease;
  }
  .bt-play{
    display:inline-flex;align-items:center;gap:7px;
    position:absolute;left:50%;top:50%;z-index:1;pointer-events:none;
    transform:translate(-50%,-50%) scale(.94);
    background:#fff;color:#17131f;
    font-size:13.5px;font-weight:600;letter-spacing:-.1px;white-space:nowrap;
    padding:9px 17px 9px 14px;border-radius:99px;
    box-shadow:0 6px 20px rgba(12,8,28,.28);
    opacity:0;transition:opacity .17s ease,transform .22s cubic-bezier(.34,1.28,.5,1);
  }
  .bt-play svg{width:15px;height:15px;flex:none}
  .bt-card:hover .bt-thumb::after,
  .bt-card:focus-visible .bt-thumb::after{opacity:1}
  .bt-card:hover .bt-play,
  .bt-card:focus-visible .bt-play{opacity:1;transform:translate(-50%,-50%) scale(1)}
  /* The hero lays out as a row — thumbnail left at 46%, copy right. Centring on
     the whole card would drop the pill into the middle of the headline, so it
     centres on the image instead. Below 640px the hero stacks back to a column
     and 50% is correct again. */
  .bt-grid.feat .bt-card:first-child .bt-play{
    left:23%;font-size:14.5px;padding:11px 21px 11px 17px;
  }
  .bt-grid.feat .bt-card:first-child .bt-play svg{width:16px;height:16px}
  @media (max-width:640px){ .bt-grid.feat .bt-card:first-child .bt-play{left:50%} }
}
@media (prefers-reduced-motion:reduce){
  .bt-card,.bt-thumb img,.bt-play,.bt-thumb::after{transition-duration:.01ms}
  .bt-card:hover{transform:none}
  .bt-card:hover .bt-thumb img{transform:none}
  .bt-play{transform:translate(-50%,-50%) scale(1)}
}
/* .bt-fmt (the "Multiple choice" / "Personality" thumbnail badge) is gone —
   it was on every card and told the reader nothing the tag and title didn't. */
.bt-body{padding:11px 12px 12px;display:flex;flex-direction:column;gap:9px;flex:1}
.bt-title{
  font-size:14px;font-weight:700;line-height:1.32;color:var(--ink);margin:0;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.bt-meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-top:auto}
.bt-pill{
  font-size:11px;font-weight:600;padding:2.5px 8px;border-radius:99px;
  background:var(--cbg,var(--primtint));color:var(--cfg,var(--primaryd));
}
.bt-len{font-size:11.5px;color:var(--muted)}
.bt-mins{font-size:11.5px;color:var(--muted)}
/* right-align the time only when something sits to its left; alone it would
   float off on its own with a leading dot separating it from nothing */
.bt-meta > .bt-mins:not(:only-child){margin-left:auto}
.bt-meta > .bt-mins:not(:only-child)::before{
  content:"";display:inline-block;width:3px;height:3px;border-radius:50%;
  background:currentColor;vertical-align:2.5px;margin-right:6px;opacity:.5}

/* featured — first card runs full width as a proper hero on desktop -------- */
.bt-grid.feat{grid-template-columns:repeat(auto-fill,minmax(216px,1fr))}
.bt-grid.feat .bt-card:first-child{grid-column:span 2;flex-direction:row;align-items:stretch}
.bt-grid.feat .bt-card:first-child .bt-thumb{flex:0 0 46%;aspect-ratio:auto;min-height:186px}
.bt-grid.feat .bt-card:first-child .bt-body{justify-content:center;padding:18px 20px;gap:11px}
.bt-grid.feat .bt-card:first-child .bt-title{
  font-family:var(--font-display);font-size:22px;line-height:1.22;letter-spacing:-.4px;-webkit-line-clamp:3;
}
.bt-blurb-sm{
  font-size:13px;color:var(--muted);line-height:1.5;margin:0;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.bt-card:not(:first-child) .bt-blurb-sm,
.bt-grid:not(.feat) .bt-blurb-sm{display:none}
@media (max-width:640px){
  /* stacked hero: full bleed of whatever track count is live */
  .bt-grid.feat .bt-card:first-child{grid-column:1/-1;flex-direction:column}
  .bt-grid.feat .bt-card:first-child .bt-thumb{flex:none;aspect-ratio:16/9;min-height:0}
  .bt-grid.feat .bt-card:first-child .bt-body{padding:12px 13px 13px}
  .bt-grid.feat .bt-card:first-child .bt-title{font-size:17px}
}

/* ---------------------------------------------------------------------------
   Category sections use the same image-forward card as "Popular this week",
   sized a little larger (3 per row rather than 4) so the titlecard art carries
   the section — matching braintrivia.net's own category rows.
   --------------------------------------------------------------------------- */
/* Fixed 3-up, not auto-fill. auto-fill silently becomes 4 columns once the rail
   collapses, which turns a six-card section into a row of four plus a ragged
   pair. The featured row gets the same treatment: its hero spans 1/-1, so the
   three cards beneath it must be exactly one row or the last one is orphaned. */
.bt-sec .bt-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}
/* Popular stays on the same 3-up track as every other section — squeezing it to
   4-up to fit five picks made those cards visibly narrower than the ones below
   them, so the row read as a different, lesser component. Instead the hero
   spans TWO columns and the fourth pick sits beside it, leaving three below:

        [ hero  hero ][ 2 ]
        [  3  ][  4  ][ 5 ]

   Five items, no ragged row, and every non-hero card is exactly the width of a
   card in the category sections. */
.bt-sec .bt-grid:not(.feat) .bt-title{font-size:14.5px}
@media (max-width:760px){
  .bt-sec .bt-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
}
@media (max-width:400px){
  .bt-sec .bt-grid{grid-template-columns:1fr}
}

/* right rail --------------------------------------------------------------- */
.bt-panel{background:var(--card);border:1px solid var(--glassbrd);border-radius:12px;padding:14px;margin:0 0 14px}
.bt-panel h3{
  font-family:var(--font-display);font-size:14px;font-weight:700;color:var(--ink);
  margin:0 0 11px;display:flex;align-items:center;gap:7px;letter-spacing:-.2px;
}
/* streak card ----------------------------------------------------------------
   braintrivia.net renders this as a dark slab on a light page. Copied straight
   across it was the only dark surface in our rail, sitting between Memo's white
   card and the white tag panel, and it read as a component borrowed from
   another site rather than part of this one.

   It is a .bt-panel now and inherits that shell entirely — surface, hairline,
   12px radius, 14px padding, and the same h3 the sibling panels use, so all
   three share one vertical rhythm. Everything below is only what the streak
   itself adds.

   The flame tile is deliberately 36px at 10px radius: identical geometry to
   .bt-sec-ico, so it reads as a sibling of the category icons rather than a
   third icon size. Amber is the one imported colour — it is the site's own
   "trending" orange (#f08a24, same as .bt-trend), so even the accent is
   already part of the palette. */
.bt-streak-h{display:flex;align-items:center;gap:10px;margin-top:2px}
.bt-flame{
  width:36px;height:36px;flex:none;border-radius:10px;
  display:grid;place-items:center;
  background:rgba(240,138,36,.16);color:#c96a12;
}
.bt-flame svg{width:21px;height:21px;display:block}
/* Lit only when there is a run to protect. A glowing flame beside "0 days"
   celebrates nothing, and makes the empty state look like the active one. */
.bt-streak:not(.is-on) .bt-flame{background:var(--pillbg);color:var(--muted)}
:root[data-theme="dark"] .bt-flame{background:rgba(240,138,36,.2);color:#ffb155}

.bt-streak-n b{
  display:block;font-family:var(--font-display);font-size:20px;font-weight:700;
  line-height:1.15;letter-spacing:-.3px;color:var(--ink);
}
.bt-streak-n span{display:block;font-size:11.5px;color:var(--muted);margin-top:1px}

.bt-stats-row{
  display:flex;gap:18px;margin-top:12px;padding-top:12px;
  border-top:1px solid var(--line);
}
.bt-sv b{
  display:block;font-family:var(--font-display);font-size:16px;font-weight:700;
  color:var(--ink);line-height:1.35;
}
.bt-sv span{display:block;font-size:11.5px;color:var(--muted)}
.bt-chips{display:flex;flex-wrap:wrap;gap:7px}
.bt-chips a{
  display:inline-flex;align-items:center;gap:5px;
  font-size:12px;font-weight:600;padding:5px 11px 5px 8px;border-radius:99px;
  background:var(--pillbg);border:1px solid var(--glassbrd);color:var(--ink);text-decoration:none;
}
.bt-chips a svg{width:14px;height:14px;flex:none;color:var(--cfg,var(--muted))}
.bt-chips a:hover{background:var(--primtint);border-color:var(--primary);color:var(--primaryd)}

/* browse-page filter bar ---------------------------------------------------- */
.bt-filter{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 20px}
.bt-fchip{
  font-size:13px;font-weight:600;padding:7px 13px;border-radius:10px;cursor:pointer;
  background:var(--card);border:1px solid var(--glassbrd);color:var(--ink);
  display:inline-flex;align-items:center;gap:6px;
}
.bt-fchip svg{width:16px;height:16px;flex:none;color:var(--cfg,var(--muted))}
.bt-fchip:hover{background:var(--pillbg)}
.bt-fchip.is-on{background:var(--primtint);border-color:var(--primary);color:var(--primaryd)}
.bt-fchip.is-on svg{color:var(--primaryd)}
.bt-fchip .n{font-size:11px;color:var(--muted);font-weight:600}
.bt-fchip.is-on .n{color:var(--primaryd)}

.bt-fchip:focus-visible,.bt-chips a:focus-visible,.bt-all:focus-visible,.bt-nav a:focus-visible{
  outline:2px solid var(--logo);outline-offset:2px;
}

/* empty state (a filter that matches nothing) ------------------------------- */
.bt-empty{
  text-align:center;padding:44px 20px;border:1px dashed var(--line);
  border-radius:12px;color:var(--muted);
}
.bt-empty b{display:block;font-family:var(--font-display);font-size:16px;color:var(--ink);margin-bottom:5px}

/* mascot picker in the rail --------------------------------------------------
   mascot.css styles .mg-picker as a standalone hero card — 18px radius, 26px
   padding, a 30px drop shadow, 140px min-height, centred with auto margins.
   Dropped into a 286px rail beside two flat .bt-panel cards it read as a
   different component that had wandered in: rounder, heavier, and on its own
   vertical rhythm. These overrides re-house it in the rail's own card shell.

   Layout is a 2x3 grid via display:contents on .mg-bubble, which promotes the
   kicker/title/CTA to the picker's grid without touching mascot.js:

       art  kick      Memo gets a tinted niche instead of floating dark-on-
       art  title     white, and the CTA spans full width instead of being
       cta  cta       squeezed into a 160px text column.

   The sound toggles move to the bottom-right corner: at the top they collided
   with the first line of the title, which is what made the card look skewed.
   --------------------------------------------------------------------------- */
.bt-rail .mg-picker{
  display:grid !important;
  grid-template-columns:auto minmax(0,1fr);
  /* Heading spans the full width like the sibling panels' h3, then Memo sits
     beside the line he is "saying", then the action. Previously the kicker was
     squeezed into the right-hand column next to him, which made it read as a
     name label floating beside a picture rather than a card heading. */
  grid-template-areas:"kick kick" "art title" "cta cta";
  align-items:center;gap:0 12px;
  margin:0 0 14px !important;max-width:none !important;width:100% !important;
  min-height:0;padding:14px;
  background:var(--card);border:1px solid var(--glassbrd);border-radius:12px;
  box-shadow:none;
}
.bt-rail .mg-picker .mg-bubble{display:contents}

/* No tinted plate behind him. I added one to stop the charcoal body floating on
   white, but a violet block is the only filled shape in the whole rail — the
   two panels below are flat white — so it read as a stray swatch rather than a
   niche, and it competed with the purple CTA directly beneath it. He sits on
   the card like he does everywhere else on the site. */
.bt-rail .mg-picker .mg-side{
  grid-area:art;flex:none;width:76px;height:76px;
  display:flex;align-items:center;justify-content:center;overflow:visible;
}
/* deliberately taller than its niche — he sits in it, not inside a box.
   MASCOT-SPEC.md: never clip him, the raised trunk leaves the viewBox. */
.bt-rail .mg-picker .mg-side .mg-owl{width:74px;height:94px}

/* The kicker becomes the panel heading — same rule as .bt-panel h3, so all
   three rail cards open identically. It was an all-caps purple eyebrow, the
   only one on the page. */
.bt-rail .mg-picker .mg-kick{
  grid-area:kick;
  font-family:var(--font-display);font-size:14px;font-weight:700;
  letter-spacing:-.2px;text-transform:none;color:var(--ink);
  margin:0 0 11px;
}
.bt-rail .mg-picker .mg-title{
  grid-area:title;align-self:center;font-size:13px;line-height:1.5;
  font-weight:400;color:var(--muted);
  margin:0;min-height:0;-webkit-line-clamp:3;
}
/* once he has actually picked something, the line IS the quiz title — promote
   it back to reading like a headline rather than supporting copy */
.bt-rail .mg-picker.has-pick .mg-title{
  font-weight:700;color:var(--ink);font-size:13.5px;line-height:1.4;
}
/* The action row holds one button before Memo has picked ("Surprise me") and
   two after ("Play this" + "Something else"). Both states are the same row, so
   the primary button is the same object throughout — it just stops being the
   only thing in it. nowrap keeps the pair on one line: with the toggles gone
   from this row there is width for both, and wrapping made the secondary look
   like a separate stray control rather than the alternative to the first. */
.bt-rail .mg-picker .mg-cta-row{
  grid-area:cta;margin-top:12px;
  display:flex;flex-wrap:nowrap;align-items:stretch;gap:10px;
}
.bt-rail .mg-picker .mg-pick{
  flex:1 1 auto;min-width:0;
  font-size:13.5px;font-weight:700;padding:9px 14px;border-radius:9px;
  /* Flat, like every other surface on this site. The stock button is a
     gradient with a 20px coloured glow — the only one of either on the page,
     and it was the loudest thing in a rail of quiet white cards. */
  background:var(--logo);box-shadow:none;
}
.bt-rail .mg-picker .mg-pick:hover{filter:brightness(1.07)}
/* align-self:stretch, not a matching padding: the secondary then shares the
   primary's box exactly, so their text sits on one baseline at any font size
   and the pair reads as one control group. */
.bt-rail .mg-picker .mg-again{
  flex:0 0 auto;align-self:stretch;display:inline-flex;align-items:center;
  font-size:12.5px;padding:0 2px;white-space:nowrap;
}
/* Toggles to the card's top-right, level with the heading.
   They were in the CTA row, which forced that row to reserve 74px on the right
   — and once Memo has picked something the row needs to hold two controls, so
   the reserved gutter pushed "Something else" onto a line of its own. They are
   chrome for the card, not part of the action, and the heading row is the only
   place they cost nothing: it is a single short line with dead space to spare.
   Placed by the grid rather than absolutely, with the heading padded clear of
   them, so a longer heading can never run underneath. */
/* The heading box is given the toggles' own height and centres its text in it,
   so the two cells in this row are the same size and line up by construction
   rather than by a nudge that would drift with the font. */
.bt-rail .mg-picker .mg-kick{
  padding-right:70px;min-height:28px;display:flex;align-items:center;
}
.bt-rail .mg-picker .mg-fx{
  /* start, not center: the heading carries an 11px bottom margin, so the row is
     taller than either box and centring in it drops the toggles 6px below the
     heading they are meant to sit level with. Both boxes are 28px and both are
     pinned to the top of the row, so they line up by construction. */
  position:static;grid-area:kick;justify-self:end;align-self:start;margin:0;
}
.bt-rail .mg-picker .mg-fx .fxtoggle{width:28px;height:28px;box-shadow:none}

/* rail stacks into a row below 1040px — keep the card from stretching tall */
@media (max-width:1040px){
  .bt-rail .mg-picker{align-content:start}
}

/* respect reduced-motion ---------------------------------------------------- */
@media (prefers-reduced-motion: reduce){
  .bt-card,.bt-card:hover,.bt-thumb img,.bt-card:hover .bt-thumb img{transition:none;transform:none}
}

/* responsive ---------------------------------------------------------------- */
@media (max-width:1040px){
  /* align-items:flex-start is set on .bt-shell for the desktop two-column
     layout. Once the shell turns into a COLUMN that property governs the cross
     axis, i.e. width — so .bt-main became fit-content instead of full width.
     The real grid got away with it because minmax(216px,1fr) tracks give it a
     large max-content width, but the skeleton's fixed-width bars do not: it
     shrank to 254px and laid out two columns where the real page lays out one.
     Stretch is what the column layout wanted all along. */
  .bt-shell{flex-direction:column;gap:0;align-items:stretch}
  /* [QA 3] align-items defaulted to stretch, so every rail panel grew to the
     height of the tallest one in its row. The tag chips and Memo's card do not
     have the content to fill that, which is the "empty space at the bottom"
     QA saw. Sizing each panel to its own content fixes both at once. */
  .bt-rail{position:static;width:100%;flex:1 1 auto;display:flex;align-items:flex-start;
           gap:14px;flex-wrap:wrap;margin-top:8px}
  .bt-rail>*{flex:1 1 260px}
}
@media (max-width:760px){
  .bt-shell{padding:16px 14px 0}
  .bt-hero h1{font-size:26px}
  .bt-stats{gap:18px}
  .bt-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px}
  .bt-grid.feat .bt-card:first-child{grid-column:span 2}
  /* [QA 3, round 2] The rail turns into a column here, and in a column flex
     container flex-basis is the MAIN axis — so `flex:1 1 260px` inherited from
     the 1040px rule above stopped meaning "at least 260px wide" and started
     meaning "at least 260px TALL". Every panel was padded out to 260px
     regardless of content, which is the empty space under "Browse by tag" and
     "Ask Memo". Panels size to their content and span the full width instead. */
  .bt-rail{flex-direction:column;align-items:stretch}
  .bt-rail>*{flex:0 0 auto;width:100%}
}

/* ==========================================================================
   Skeleton / loading state
   --------------------------------------------------------------------------
   QA: "no structure / fishbones appear before the actual tiles load."

   They were right, and the cause is structural rather than cosmetic: the
   listing pages ship an EMPTY <main id="btRoot">, and every tile is written by
   bt-listing.js after quizzes.js has parsed. Between first paint and that
   moment the page is the header, the footer, and nothing — on a slow
   connection long enough to read as a broken page.

   The skeleton is therefore emitted as static HTML inside #btRoot at build
   time, not drawn by script: markup that needs JavaScript to appear cannot
   cover the window where JavaScript has not run yet. bt-listing.js already
   assigns root.innerHTML, so it clears the skeleton by construction — there is
   no teardown to keep in sync, and no state where both are visible.

   Two details worth keeping:

   - .bt-skel starts at opacity 0 and fades in after 140ms. On a warm cache the
     real grid lands in well under that, so the common path shows no skeleton
     at all rather than a one-frame flash of grey, which reads worse than the
     blank it replaced.
   - Under prefers-reduced-motion the sweep stops but the blocks stay. The
     point of the skeleton is the layout, not the shimmer; removing the shapes
     would take the meaning away from the people the query is protecting.
   ========================================================================== */
:root{ --skb:#e7e7e3; --skh:#f5f5f2 }
:root[data-theme="dark"]{ --skb:#24242c; --skh:#32323d }

.bt-skel{opacity:0;animation:sk-in .18s ease-out 140ms forwards}
@keyframes sk-in{to{opacity:1}}

.sk{
  display:block; border-radius:7px; background:var(--skb);
  /* 200% wide gradient slid across the box — one compositor-friendly property
     animating, and it costs nothing when the element is replaced mid-sweep. */
  background-image:linear-gradient(90deg,var(--skb) 0%,var(--skh) 45%,var(--skb) 90%);
  background-size:220% 100%; background-repeat:no-repeat;
  animation:sk-sweep 1.3s ease-in-out infinite;
}
@keyframes sk-sweep{ from{background-position:150% 0} to{background-position:-60% 0} }

/* hero */
.sk-hero{display:flex;align-items:flex-start;justify-content:space-between;gap:28px;flex-wrap:wrap;margin:0 0 26px}
.sk-hero-t{flex:1 1 380px;min-width:0}
.sk-h1{height:26px;margin:0 0 10px;max-width:420px}
.sk-h1.w2{max-width:330px;margin-bottom:16px}
.sk-p{height:11px;max-width:520px;margin:0 0 8px}
.sk-p.w6{max-width:300px}
.sk-stats{display:flex;gap:26px;flex:0 0 auto;padding-top:4px}
.sk-stat{width:58px;height:38px}

/* section header — icon tile + two text lines + the "All N" link */
.sk-sec{margin:0 0 30px}
.sk-sech{display:flex;align-items:center;gap:11px;margin:0 0 14px}
.sk-ico{width:38px;height:38px;border-radius:11px;flex:none}
.sk-sect{flex:1 1 auto;min-width:0}
.sk-sect .sk{height:13px;max-width:150px;margin:0 0 6px}
.sk-sect .sk:last-child{height:10px;max-width:250px;margin:0}
.sk-all{width:56px;height:14px;flex:none}

/* card grid — mirrors .bt-sec .bt-grid exactly so the swap doesn't shift layout */
.sk-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}
.sk-card{background:var(--card);border:1px solid var(--line);border-radius:14px;overflow:hidden}
.sk-thumb{aspect-ratio:16/9;border-radius:0}
.sk-cb{padding:11px 12px 12px}
.sk-cb .sk{height:12px;margin:0 0 7px}
.sk-cb .sk.w7{max-width:78%}
.sk-cb .sk.meta{height:16px;max-width:96px;border-radius:99px;margin:11px 0 0}
/* featured row: hero spans two columns and lays out side-by-side, like the real one */
.sk-grid.feat > .sk-card:first-child{grid-column:span 2;display:flex}
.sk-grid.feat > .sk-card:first-child .sk-thumb{flex:0 0 46%;aspect-ratio:auto;min-height:186px}
.sk-grid.feat > .sk-card:first-child .sk-cb{flex:1;padding:18px 20px;align-self:center;width:100%}

/* rail */
.sk-panel{background:var(--card);border:1px solid var(--glassbrd);border-radius:12px;padding:14px;margin:0 0 14px}
.sk-panel .sk-ph{height:13px;max-width:120px;margin:0 0 12px}
.sk-chips{display:flex;flex-wrap:wrap;gap:7px}
.sk-chip{height:26px;border-radius:99px;flex:0 0 auto}
.sk-row{display:flex;gap:12px;align-items:center}
.sk-avatar{width:74px;height:94px;border-radius:12px;flex:none}
.sk-lines{flex:1 1 auto;min-width:0}
.sk-lines .sk{height:11px;margin:0 0 8px}
.sk-cta{height:38px;border-radius:10px;margin-top:12px}

/* filter chip strip (browse page) */
.sk-filter{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 20px}
.sk-fchip{height:32px;border-radius:99px;flex:0 0 auto}

/* ---- reserve the real heights -------------------------------------------
   A skeleton that occupies a different amount of space than the content it
   stands in for is a layout shift with extra steps. These are measured off the
   live page rather than guessed, at both breakpoints:

                       390px            1280px
     hero              217              213
     section header     57               41
     card thumb        203 (16/9)       142 (16/9)
     card body          66               85
     featured card     329 stacked      231 side-by-side

   Only the bodies and the two fixed blocks need pinning; the thumbs already
   derive from the same 16/9 the real cards use. */
.sk-cb{min-height:85px}
.sk-hero{min-height:213px}
.sk-sech{min-height:41px}
.sk-grid.feat > .sk-card:first-child .sk-thumb{min-height:229px}

@media (max-width:1040px){
  .sk-rail{display:flex;gap:14px;flex-wrap:wrap;align-items:flex-start;margin-top:8px}
  .sk-rail>*{flex:1 1 260px}
}
@media (max-width:760px){
  .sk-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .sk-grid.feat > .sk-card:first-child{grid-column:span 2;display:block}
  .sk-grid.feat > .sk-card:first-child .sk-thumb{aspect-ratio:16/9;min-height:0}
  .sk-grid.feat > .sk-card:first-child .sk-cb{padding:12px 13px 13px;min-height:125px}
  .sk-h1{height:22px}
  /* One title bar, not two: at full card width the real titles fit on a single
     line here, so a second bar made the skeleton 15px taller than the card
     that replaces it. The featured card keeps both — its title genuinely wraps. */
  .sk-grid:not(.feat) .sk-cb .sk.w7{display:none}
  .sk-cb{min-height:66px}
  .sk-hero{min-height:217px}
  .sk-sech{min-height:57px}
  .sk-rail{flex-direction:column}
  .sk-rail>*{flex:0 0 auto;width:100%}
}
@media (max-width:400px){ .sk-grid{grid-template-columns:1fr} }

@media (prefers-reduced-motion:reduce){
  .bt-skel{animation:none;opacity:1}
  .sk{animation:none;background-image:none}
}
