/* ══════════════════════════════════════════════════════════════════════
   HOME SECTION GALLERY — three coverflow rows, and "step into the frame"
   ══════════════════════════════════════════════════════════════════════

   Home's navigator. THREE ROWS, stacked one above the other — today's quick
   wins, deep work, reference & rewards. Each row is a self-contained
   coverflow: one framed cover faces you, the rest are turned away on either
   side, and turning one row never moves another. Pressing the cover in front
   pulls you into it and lands on that page.

   The picture on a cover is a MINIATURE OF THAT SECTION'S OWN SCREEN, not an
   app icon — see HOME_SECTION_PREVIEWS in scripts/core/app-legacy.js for what
   they are and the three rules they follow. All the `.mk-*` classes at the
   bottom of this file are that miniature's vocabulary.

   COLOUR IS PER ROW. `--ims-glow` is set once on `.hg-row` and inherits to
   everything inside it — the ambient light, the screen tint, the accents in
   the miniature, the active dot. That makes "one colour per row" true by
   construction rather than by nine literals that have to agree, and it is why
   no rule below names a section.

   FAIL-OPEN CONTRACT (same shape as the intro overlay's, and for the same
   reason). Every coverflow rule lives behind `.hg.is-ready`, which
   scripts/features/home-gallery.js adds once it has bound its controls.
   Without that class each `.hg-flow` is an ordinary wrapping row of covers —
   all nine visible, all nine openable — and the arrows and dots are hidden. So
   a home-gallery.js that fails to load costs the flow, never the navigation.
   Never move a positioning rule out of `.is-ready`: every cover but one per
   row would become invisible AND unreachable.

   The covers keep .home-section-pill-emoji / -name / -sub on purpose. Three
   badge systems hang off those hooks — the daily-task dot
   (scripts/features/daily-nav-dots.js), The Ward's Event! pill and Exam Edge's
   Premium pill — and re-pointing all three at new class names to rename a box
   is how one of them quietly stops painting. theme.css still owns the badges.
   ══════════════════════════════════════════════════════════════════════ */

.hg {
  /* --cw is the cover width and the ONE number the whole component scales
     from: the frame, the stage height, the arrows' distance from the
     nameplate, the spread of the turned covers, and the type inside the
     miniatures. Change it per breakpoint, nothing else.
     It is deliberately smaller than a single-flow gallery would want: three
     stages are stacked down the page now, so every extra pixel of cover height
     is paid three times. */
  --cw: 168px;
  /* Card height (4:5) plus the band under it that the floor reflection fades
     out in — the stage clips at the end of that band. */
  --ch: calc(var(--cw) * 5 / 4 + 3.5rem);
  max-width: 780px;
  margin: 0 auto;
  /* Transparent: Home paints an animated scene canvas behind the page and the
     gallery is meant to stand in it. Everything carrying TEXT is opaque or
     shadowed for its own sake. */
  background: transparent;
}
@media (min-width: 400px) { .hg { --cw: 192px; } }
@media (min-width: 560px) { .hg { --cw: 212px; } }
@media (min-width: 900px) { .hg { --cw: 236px; } }

/* ── A row ──────────────────────────────────────────────────────────── */

.hg-row + .hg-row { margin-top: 2.4rem; }

.hg-head { margin-bottom: 0.4rem; }
.hg-head .home-group-title { margin-bottom: 0.2rem; }
.hg-head .home-group-pull { margin-bottom: 0; }

/* Stage + its light + its arrows. Positioning context for all three. */
.hg-deck { position: relative; }

/* ── The row's light ────────────────────────────────────────────────── */
/* ONE soft blob per row, and the row's main colour signal.
   * A SIBLING of .hg-stage, never a child. The stage clips — that is what
     crops the turned covers — so a light inside it would be cut off at exactly
     the edges it needs to bleed past.
   * ONE gradient, blurred, with a falloff that reaches full transparency at
     its own box edge. An earlier version used three lobes to get brightness
     around the opaque centre cover and every lobe boundary read as a seam;
     the fix is a bigger blob and a blur, not more of them.
   * Sized beyond the covers so the part you actually see — the ring that
     emerges from behind the cover in front — is still near full strength, but
     NOT past the row: the page's own ground has to survive at the edges. It
     did not until v0.9.06. The blob was wider than a phone viewport at 0.42
     over a near-black ground, so the whole band took the row's hue and Home's
     ground was simply gone between the hero and the leaderboards — which is
     invisible on the navy it was tuned against and glaring under Premium,
     where the one thing a pass buys on this page is a purple room.
   * It composites as LIGHT (mix-blend-mode: screen), not as paint. Screen can
     only add, so the ground's own hue is never subtracted and a teal row over
     a purple Home reads as purple lit teal. Strength is what actually fixed
     the wash; the blend is what keeps it honest as the ground changes. */

.hg-glow {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(104%, calc(var(--cw) * 2.35));
  height: calc(var(--ch) + 3rem);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(closest-side,
    var(--ims-glow, var(--ims-brand)) 0%, transparent 100%);
  filter: blur(46px);
  opacity: 0.3;
  mix-blend-mode: screen;
  pointer-events: none;
  z-index: 0;
}
/* Everything else stands in front of the light. */
.hg-stage { position: relative; z-index: 1; }

/* ── Controls ───────────────────────────────────────────────────────── */
/* One cluster under the deck: ‹ arrow — the active card's title/subtitle
   badge — arrow ›, then the index pills. The arrows flank the NAME because
   they are the control for "which card am I looking at"; above the deck they
   moved whenever the heading wrapped, and over the cards they sat on the
   turned ones they exist to bring forward.
   The badge is shared rather than per-card because the cards carry a floor
   reflection, and a caption under a card is exactly where its reflection
   falls. Hidden until .is-ready — without the script nothing is "active", so
   each cover shows its own caption instead (see .hg-name). */

.hg-controls { display: none; }
.hg.is-ready .hg-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  margin-top: 0.7rem;
}
.hg-arrow {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  /* Opaque, like every other control Home puts over the scene canvas. */
  background: #16224a;
  border: 1.5px solid rgba(var(--ims-brand-rgb), 0.55);
  border-radius: 10px;
  color: #dcebff;
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.hg-arrow svg { width: 17px; height: 17px; display: block; }
.hg-arrow:hover { background: #1e2f63; border-color: var(--ims-brand-mid); }
.hg-arrow:active { transform: scale(0.94); }
.hg-arrow:focus-visible { outline: 2px solid var(--ims-brand-lite); outline-offset: 2px; }
/* Wraps around rather than disabling: a row is two to five cards, and a
   disabled control at either end is one the user has to work out the rule for. */

/* The badge. Fixed width so the arrows keep their place as the name changes —
   a control that shifts sideways under the finger between presses is the one
   thing a stepper must not do. Opaque, like everything else Home puts over the
   scene canvas. */
.hg-badge {
  flex: 0 0 auto;
  width: var(--cw);
  min-width: 0;
  margin: 0;
  padding: 0.34rem 0.5rem;
  border-radius: 8px;
  text-align: center;
  background: linear-gradient(180deg, #22304f 0%, #16203a 100%);
  border-top: 1px solid rgba(245, 158, 11, 0.35);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 2px 6px rgba(0, 0, 0, 0.45);
  overflow-wrap: break-word;
}
.hg .hg-badge .home-section-pill-name {
  display: block;
  font-size: 0.9rem;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.hg .hg-badge .home-section-pill-sub {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  margin-top: 0.08rem;
  font-size: 0.68rem;
  line-height: 1.25;
  color: rgba(196, 219, 245, 0.78);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
}
@media (max-width: 359px) {
  .hg .hg-badge .home-section-pill-name { font-size: 0.82rem; }
  .hg .hg-badge .home-section-pill-sub { font-size: 0.63rem; }
}

/* Index pills. */
.hg-dots { display: none; }
.hg.is-ready .hg-dots {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  margin-top: 0.45rem;
}
.hg-dot {
  width: 26px;
  height: 26px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  cursor: pointer;
}
/* The 26px button is the tap target; the pill inside it is what you see. */
.hg-dot::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(170, 200, 235, 0.35);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
  transition: width 0.24s cubic-bezier(0.25, 1, 0.5, 1), background 0.24s ease;
}
.hg-dot[aria-current="true"]::before {
  width: 18px;
  border-radius: 99px;
  /* Its row's colour, inherited — the control and the light agree without
     either of them naming a section. */
  background: var(--ims-glow, var(--ims-brand-lite));
}
.hg-dot:hover::before { background: rgba(200, 225, 255, 0.7); }
.hg-dot:focus-visible { outline: 2px solid var(--ims-brand-lite); outline-offset: 1px; border-radius: 8px; }

/* ── The stage ──────────────────────────────────────────────────────── */

.hg-flow {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.6rem 1.2rem;
}

.hg.is-ready .hg-stage {
  /* The turned covers run off both edges on purpose; this is what crops them.
     The extra height is headroom for the corner badges, which overhang the top
     of the frame by 7px and would otherwise be sliced by this same clip. */
  overflow: hidden;
  height: calc(var(--ch) + 1.5rem);
  padding-top: 0.9rem;
  /* Horizontal drags turn the row; vertical scrolling stays native. */
  touch-action: pan-y;
}
.hg.is-ready .hg-flow {
  display: block;
  position: absolute;
  inset: 0.9rem 0 0;
  /* Perspective belongs HERE, not on .hg-stage. It applies to an element's
     own children, and the covers are children of the flow — with it a level up
     the rotateY values still applied but resolved flat, so every "turned"
     cover rendered face-on and the whole effect was missing. Putting it on the
     flow also keeps `overflow: hidden` on the stage, which would have
     flattened a preserve-3d chain anyway. */
  perspective: 1200px;
  perspective-origin: 50% 46%;
  /* Not strictly required — the covers are direct children of this element, so
     each already resolves against the perspective above. Declared because the
     deck is a 3D scene and a future nested wrapper would silently flatten it. */
  transform-style: preserve-3d;
}
.hg.is-ready .hg-cover {
  position: absolute;
  top: 0;
  left: 50%;
  margin-left: calc(var(--cw) / -2);
  /* home-gallery.js writes transform, opacity and z-index on every cover. */
  /* The spec's spring, expressed as its cubic-bezier equivalent — this project
     has no animation library and adding one for a nine-element deck would be a
     build step for a curve. */
  transition:
    transform 0.55s cubic-bezier(0.25, 1, 0.5, 1),
    opacity 0.45s cubic-bezier(0.25, 1, 0.5, 1),
    filter 0.45s cubic-bezier(0.25, 1, 0.5, 1);
}
/* Mid-gesture the cards are driven frame by frame, so CSS must not also be
   easing them. `will-change` is added HERE rather than permanently: it promotes
   each card to its own compositor layer, which is exactly what makes the drag
   cheap — and nine permanent layers per row is memory spent on a page that is
   usually just being scrolled past.
   Paying for the promotion at gesture start is deliberate. A single hitch as
   the finger lands is far better than a stutter through the whole swipe, which
   is what this trades away. */
.hg-row.is-dragging .hg-cover {
  transition: none;
  will-change: transform, opacity;
}
/* The card's own hover/press easing would fight the frame-by-frame writes too. */
.hg-row.is-dragging .hg-screen,
.hg-row.is-dragging .hg-badge,
.hg-row.is-dragging .hg-screen::before { transition: none; }

@media (prefers-reduced-motion: reduce) {
  .hg.is-ready .hg-cover { transition: none; }
}

/* ── One cover ──────────────────────────────────────────────────────── */

.hg-cover {
  width: var(--cw);
  /* A flex item's automatic minimum size is its min-content width, which for
     an unbreakable nameplate ("MedConnections") is wider than --cw — in the
     fallback row that made one cover bigger than its neighbours. */
  min-width: 0;
  flex: 0 0 auto;
  display: block;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  text-align: center;
}
.hg-cover:focus-visible { outline: none; }

/* The frame. Also .home-section-pill-emoji, so it must stay `position:
   relative` and must NOT clip — all three badges are absolutely positioned to
   overhang its corners. The screen is clipped one level in, by .hg-mock. */
.hg .hg-screen {
  position: relative;
  isolation: isolate;
  display: block;
  width: 100%;
  max-width: none;
  aspect-ratio: 4 / 5;
  margin: 0;
  /* A 2px amber edge rather than the thick gilt moulding this started with.
     The dimmer amber is the resting state; the cover in front takes the bright
     one, below — the border is part of how you tell which card is live. */
  padding: 0;
  border: 2px solid #D97706;
  border-radius: 10px;
  background: none;
  /* Depth first, then the amber bloom. Both are on the card rather than on a
     wrapper so the reflection below picks them up. */
  box-shadow:
    0 25px 50px -12px rgba(0, 0, 0, 0.7),
    0 0 30px 2px rgba(245, 158, 11, 0.25);
  overflow: visible;
  transition: border-color 0.45s cubic-bezier(0.25, 1, 0.5, 1),
              box-shadow 0.45s cubic-bezier(0.25, 1, 0.5, 1);
}
.hg.is-ready .hg-cover.is-focus .hg-screen {
  border-color: #F59E0B;
  box-shadow:
    0 25px 50px -12px rgba(0, 0, 0, 0.7),
    0 0 30px 2px rgba(245, 158, 11, 0.25),
    0 0 60px 6px rgba(245, 158, 11, 0.18);
}

/* Floor reflection.
   `-webkit-box-reflect` is the whole implementation where it exists (Chrome,
   Edge, Safari — and it costs no extra DOM, which matters because the
   alternative is cloning nine miniatures' worth of nodes onto a page that is
   already painting an animated canvas behind it).
   Firefox has never implemented it and there is no standard equivalent, so it
   falls back to the soft floor ellipse below — the card still stands on
   something, it just is not mirrored. That degradation is deliberate: a
   duplicated, flipped, masked copy of every card is a real cost for the ~3% of
   sessions that would see it. */
.hg.is-ready .hg-screen {
  -webkit-box-reflect: below 12px linear-gradient(to bottom, transparent 50%, rgba(0, 0, 0, 0.45));
}

/* theme.css gives .home-section-pill-emoji a bevel sheen and a blurred halo
   through its pseudo-elements. Both are re-tasked here — ::before is the
   section's coloured light, ::after is the floor the cover stands on — so
   neither inherited rule is left half-applied. */
/* A faint rim, nothing more — the ambient column above is what carries the
   colour now. Off entirely on the turned covers: seven of these composited
   into a flat wash, which is the version .hg-glow replaced. */
.hg .hg-screen::before {
  content: '';
  position: absolute;
  inset: -14%;
  border-radius: 18px;
  background: var(--ims-glow, var(--ims-brand));
  filter: blur(26px);
  opacity: 0;
  z-index: -2;
  pointer-events: none;
  transition: opacity 0.4s ease;
}
/* A soft ellipse under the card. Universal ground, and the whole of the floor
   effect in Firefox, which has no -webkit-box-reflect. */
.hg .hg-screen::after {
  content: '';
  position: absolute;
  left: 6%;
  right: 6%;
  bottom: -13px;
  height: 20px;
  border-radius: 50%;
  background: radial-gradient(ellipse at 50% 50%,
    rgba(0, 0, 0, 0.62) 0%, rgba(0, 0, 0, 0.3) 48%, transparent 76%);
  z-index: -1;
  pointer-events: none;
}

/* The screen. Clips, so a miniature can never spill over the moulding; the
   badges live on .hg-screen outside this box and stay visible. */
.hg-mock {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 8px;
  overflow: hidden;
  /* The card's own ground, from its real page (HOME_SECTION_SKINS in
     app-legacy). The fallback is the shared dark navy, so a section with no
     skin still reads as a screen. */
  background: var(--mk-bg, linear-gradient(168deg, #101c37 0%, #0b1428 58%, #080e1e 100%));
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.8),
    inset 0 6px 18px rgba(0, 0, 0, 0.5);
  /* Everything inside a miniature is sized in em off this, so one set of
     markup works from a 320px phone to the desktop hero size. */
  font-size: calc(var(--cw) / 21);
  font-family: 'DM Sans', sans-serif;
  text-align: left;
}
/* Top-light over the screen's ground, in the CARD's accent. A pseudo-element
   with opacity rather than color-mix(): a browser that drops a color-mix()
   declaration would paint all nine screens identically, losing the one cue
   that tells them apart at a glance. */
.hg-mock::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 62% at 50% 0%, var(--mk-acc, var(--mk-acc, var(--ims-glow, #4472c4))) 0%, transparent 70%);
  opacity: 0.18;
  pointer-events: none;
}

/* Corner wash, under the card's big object and over the screen's own content,
   so the UI stays legible where the two overlap. Lives on .hg-mock because the
   object is an <svg> and pseudo-elements are not rendered on SVG elements. */
.hg-mock::after {
  content: '';
  position: absolute;
  right: -18%;
  bottom: -18%;
  width: 88%;
  height: 76%;
  z-index: 2;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(5, 3, 1, 0.8) 0%, transparent 78%);
  pointer-events: none;
}

/* Glass over the screen: a fixed diagonal sheen and a vignette, so the cover
   reads as something behind glass rather than a flat sticker. */
.hg-gloss {
  position: absolute;
  inset: 6px;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(116deg,
      rgba(255, 255, 255, 0.14) 0%, rgba(255, 255, 255, 0.035) 24%,
      rgba(255, 255, 255, 0) 44%),
    radial-gradient(120% 100% at 50% 6%,
      rgba(255, 255, 255, 0.06) 0%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.4) 100%);
}

/* The card's own name. The deck shows it in the shared badge under the
   controls, so when the script is running this is here only to give the button
   an accessible name — daily-nav-dots.js reads `btn.textContent` for its base
   label, and only ever supplies a fallback for the five sections it tracks.
   Without the script nothing is "active" and there is no shared badge, so it
   renders as an ordinary caption under each card. */
.hg-name {
  display: block;
  margin-top: 0.55rem;
  text-align: center;
  overflow-wrap: break-word;
}
.hg .hg-name .home-section-pill-name { display: block; font-size: 0.9rem; }
.hg .hg-name .home-section-pill-sub { display: block; margin-top: 0.1rem; font-size: 0.7rem; }
.hg.is-ready .hg-name {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── The card in front ──────────────────────────────────────────────── */
/* Only this one opens on a press; the turned ones turn to face you first (see
   imsHomeCoverClick in app-legacy.js). So it has to be unmistakably the one
   that is live — it is the only card at full scale, full opacity and full
   brightness (home-gallery.js writes those), it takes the bright amber border
   and the wider bloom, and its own rim light comes up. */

.hg.is-ready .hg-cover.is-focus .hg-screen::before { opacity: 0.18; }
/* A turned card is a smaller, rotated target, so give the pointer a hint that
   pressing it does something before it does it. */
.hg.is-ready .hg-cover:not(.is-focus):hover .hg-screen::before { opacity: 0.12; }
.hg-cover:focus-visible .hg-screen {
  box-shadow:
    0 0 0 3px var(--ims-brand-lite),
    0 25px 50px -12px rgba(0, 0, 0, 0.7),
    0 0 30px 2px rgba(245, 158, 11, 0.25);
}

/* ── Stepping into the frame ────────────────────────────────────────── */
/* A clone of the card, mounted on <body> and scaled up until it covers the
   viewport, with the world going black AS it grows — so the page swap happens
   in the dark and the new section fades up out of it, rather than the old page
   showing around a shrinking gap.
   Mounted on the body for the documented reason: .page's own fade animates
   `transform`, and a transformed ancestor becomes the containing block for
   position:fixed descendants. Never blocks input — the page behind it is
   already live. */

.hg-jump {
  position: fixed;
  inset: 0;
  z-index: 2600;
  pointer-events: none;
  overflow: hidden;
  contain: strict;
}
/* The veil sits ABOVE the flying card, not behind it. Behind, the card is
   opaque and covers the veil completely, so the black was invisible until the
   card faded — which reads as "zoom, and THEN fade to black". Above, the whole
   scene darkens while the card is still growing, which is the fade happening
   DURING the zoom. */
.hg-jump-veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: #000;
  opacity: 0;
  /* Reaches full black just as the card finishes growing. */
  transition: opacity 0.44s ease;
}
.hg-jump.is-in .hg-jump-veil { opacity: 1; }
/* Out: the black lifts, revealing the page that was swapped in underneath it.
   Only ever added once the new page has actually painted — see stepInto(). */
.hg-jump.is-out .hg-jump-veil {
  opacity: 0;
  transition: opacity 0.4s ease;
}
.hg-jump-art {
  position: absolute;
  z-index: 1;
  transform-origin: 50% 50%;
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 0 0 0 6px rgba(168, 130, 63, 0.9), 0 20px 60px rgba(0, 0, 0, 0.7);
  transition: transform 0.52s cubic-bezier(0.5, 0, 0.35, 1);
  will-change: transform;
}
/* Struck while the screen is fully black, never faded. A fade would mean the
   card is still on screen as the veil lifts — which is exactly how a huge
   zoomed-in copy of the card ended up flashing back at the end of the
   transition. Once it is black, the card's job is done. */
.hg-jump.is-dark .hg-jump-art { display: none; }

/* ══════════════════════════════════════════════════════════════════════
   THE MINIATURES
   ══════════════════════════════════════════════════════════════════════
   One shared vocabulary rather than nine bespoke stylesheets, so a tenth
   section costs a template string in HOME_SECTION_PREVIEWS and no CSS. Every
   size is in em off .hg-mock's font-size, and every accent is --ims-glow, so a
   miniature is correct at any cover size and colour-matched to its section
   with no per-section rules.

   These are decoration: the markup is aria-hidden and the cover's accessible
   name is the plate under it. That is why the type here is allowed below the
   0.8rem floor the study-stats panel keeps — nothing in a miniature is content
   to be read, and a screen reader is never handed it.
   ══════════════════════════════════════════════════════════════════════ */

.mk {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.5em;
  height: 100%;
  padding: 1em 0.9em;
  color: #e8f0fb;
  line-height: 1.2;
}
.mk i, .mk b, .mk em { font-style: normal; }

.mk-lab {
  font-size: 0.72em;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: rgba(178, 205, 238, 0.62);
  text-align: center;
}
.mk-hero {
  font-size: 2.7em;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  color: #fff;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.mk-foot {
  margin-top: auto;
  font-size: 0.74em;
  color: rgba(178, 205, 238, 0.6);
  text-align: center;
}
.mk-streak { color: #ffb454; font-weight: 700; }

/* Start ring — The Ward's play button. */
.mk-ring {
  width: 4.4em;
  height: 4.4em;
  margin: 0.1em auto;
  border-radius: 50%;
  border: 0.16em solid var(--mk-acc, var(--ims-glow, #4472c4));
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.04);
}
.mk-ring i {
  width: 0;
  height: 0;
  margin-left: 0.25em;
  border-left: 0.95em solid #fff;
  border-top: 0.62em solid transparent;
  border-bottom: 0.62em solid transparent;
}

/* Pills. */
.mk-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3em;
  align-items: center;
  justify-content: center;
}
.mk-chip {
  font-size: 0.76em;
  font-weight: 600;
  padding: 0.28em 0.62em;
  border-radius: 99px;
  border: 1px solid rgba(160, 190, 230, 0.28);
  color: rgba(200, 222, 246, 0.8);
  white-space: nowrap;
}
.mk-chip.on {
  border-color: var(--mk-acc, var(--ims-glow, #4472c4));
  background: rgba(255, 255, 255, 0.09);
  color: #fff;
}
.mk-tag {
  font-size: 0.66em;
  letter-spacing: 0.1em;
  font-weight: 700;
  color: rgba(178, 205, 238, 0.5);
}

/* Grids — MedWordle's board, MedConnections' words, the Shop's tiles. */
.mk-grid {
  display: grid;
  grid-template-columns: repeat(var(--c, 4), 1fr);
  gap: 0.28em;
}
.mk-grid > i {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0.18em;
  border: 1px solid rgba(160, 190, 230, 0.24);
  font-size: 0.92em;
  font-weight: 800;
  color: #fff;
}
.mk-grid > i.on { background: #2f9e63; border-color: #2f9e63; }
.mk-grid > i.warm { background: #c39b3a; border-color: #c39b3a; }
/* Pushes what follows to the foot of the screen — the keyboard sits at the
   bottom of MedWordle's board the way a real one does, instead of leaving the
   lower half of the cover empty. A class, not :first-of-type: every child of
   .mk is a <span>, so the type selector matched the label at the top. */
.mk > .mk-push { margin-top: auto; }
.mk-keys { display: flex; gap: 0.22em; justify-content: center; }
.mk-keys i {
  flex: 1 1 0;
  height: 1.15em;
  border-radius: 0.16em;
  background: rgba(160, 190, 230, 0.2);
}
.mk-words { flex: 1 1 auto; align-content: space-evenly; }
.mk-words > i {
  aspect-ratio: auto;
  padding: 0.5em 0.2em;
  font-size: 0.72em;
  font-weight: 700;
  text-align: center;
  background: rgba(255, 255, 255, 0.05);
}
.mk-words > i.sel {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.4);
}
.mk-band {
  padding: 0.55em;
  border-radius: 0.28em;
  background: var(--mk-acc, var(--ims-glow, #4472c4));
  color: #10152a;
  font-size: 0.76em;
  font-weight: 800;
  text-align: center;
}
.mk-tiles { flex: 1 1 auto; align-content: space-evenly; }
.mk-tiles > i {
  aspect-ratio: auto;
  display: flex;
  flex-direction: column;
  /* Resets the `align-items: center` inherited from .mk-grid > i, which is
     right for a lettered cell and wrong here: it sized the empty art block to
     its content — zero — so every shop tile rendered as a bare price. */
  align-items: stretch;
  gap: 0.3em;
  padding: 0.4em;
  border-radius: 0.28em;
  background: rgba(255, 255, 255, 0.05);
}
.mk-tiles > i > b {
  height: 2.1em;
  border-radius: 0.2em;
  background: linear-gradient(150deg, #4b6bd8, #2b3f8f);
}
.mk-tiles > i > b.alt { background: linear-gradient(150deg, #c9822f, #7c4a15); }
.mk-tiles > i > b.alt2 { background: linear-gradient(150deg, #3f9e7a, #1d5c46); }
.mk-tiles > i > em { font-size: 0.7em; font-weight: 700; color: #ffd24a; text-align: center; }
.mk-coin {
  align-self: center;
  font-size: 0.82em;
  font-weight: 800;
  color: #ffd24a;
  padding: 0.28em 0.7em;
  border-radius: 99px;
  background: rgba(255, 210, 74, 0.12);
  border: 1px solid rgba(255, 210, 74, 0.4);
}

/* Duels. */
.mk-vs { display: flex; align-items: center; justify-content: center; gap: 0.6em; }
.mk-vs b { font-size: 0.86em; font-weight: 800; color: rgba(200, 222, 246, 0.75); }
.mk-ava {
  width: 1.9em;
  height: 1.9em;
  border-radius: 50%;
  background: linear-gradient(150deg, #4b6bd8, #23306b);
  border: 1px solid rgba(255, 255, 255, 0.25);
}
.mk-ava.alt { background: linear-gradient(150deg, #d8734b, #6b2a23); }
.mk-q { font-size: 0.82em; font-weight: 600; color: #eaf2ff; }
.mk-opt {
  display: block;
  padding: 0.4em 0.55em;
  border-radius: 0.28em;
  border: 1px solid rgba(160, 190, 230, 0.24);
  font-size: 0.74em;
  color: rgba(214, 231, 250, 0.85);
}
.mk-opt.on {
  border-color: var(--mk-acc, var(--ims-glow, #4472c4));
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font-weight: 700;
}

/* Lists — Scrub In's goals, Exam Edge's decks, the Study Guide's subjects.
   The list takes the leftover height and spreads its rows through it, rather
   than bunching at the top over a void. One rule instead of hand-tuned filler
   content in four previews, and it keeps working when a row is added. */
.mk-list {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  justify-content: space-evenly;
  gap: 0.32em;
}
.mk-row { display: flex; align-items: center; gap: 0.45em; font-size: 0.78em; }
.mk-row em { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-row.done em { color: rgba(178, 205, 238, 0.5); text-decoration: line-through; }
.mk-box {
  flex: 0 0 auto;
  width: 1.15em;
  height: 1.15em;
  border-radius: 0.2em;
  border: 1px solid rgba(160, 190, 230, 0.4);
}
.mk-box.on {
  background: var(--mk-acc, var(--ims-glow, #4472c4));
  border-color: var(--mk-acc, var(--ims-glow, #4472c4));
}
.mk-pip {
  flex: 0 0 auto;
  width: 0.6em;
  height: 0.6em;
  border-radius: 50%;
  background: var(--mk-acc, var(--ims-glow, #4472c4));
}
.mk-pip.alt { background: #d8734b; }

/* Bars and skeleton lines. */
.mk-bar {
  display: block;
  height: 0.42em;
  border-radius: 99px;
  background: rgba(160, 190, 230, 0.2);
  overflow: hidden;
}
.mk-bar > i, .mk-bar > span {
  display: block;
  width: var(--w, 50%);
  height: 100%;
  border-radius: 99px;
  background: var(--mk-acc, var(--ims-glow, #4472c4));
}
.mk-bar.sm { flex: 0 0 3.2em; }
.mk-line {
  display: block;
  width: var(--w, 100%);
  height: 0.42em;
  border-radius: 99px;
  background: rgba(160, 190, 230, 0.26);
}

/* Cards. Never stretch: a card is a fixed thing on a page, and a list beside
   it is what should take the slack. */
.mk-card {
  flex: 0 0 auto;
  /* .mk-grow opts one card into taking the slack — a flashcard IS the page it
     sits on, so Daily Pearls' card fills the screen while The Ward's companion
     strip stays a strip. */
  display: flex;
  flex-direction: column;
  gap: 0.45em;
  padding: 0.75em 0.65em;
  border-radius: 0.34em;
  border: 1px solid rgba(160, 190, 230, 0.22);
  background: rgba(255, 255, 255, 0.04);
}
/* The Ward's companion strip, under the timer controls. */
.mk-pet { align-items: center; gap: 0.35em; margin-top: auto; }
.mk-pet-ava {
  width: 2.1em;
  height: 2.1em;
  border-radius: 50%;
  background: linear-gradient(150deg, #9b6dff, #4a2b8f);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3);
}
.mk-pet b { font-size: 0.72em; font-weight: 700; color: rgba(224, 236, 252, 0.9); }
.mk-pet .mk-bar { width: 78%; }
.mk-card.mk-grow { flex: 1 1 auto; }
.mk-reveal {
  margin-top: auto;
  padding-top: 0.5em;
  font-size: 0.74em;
  font-weight: 700;
  color: var(--mk-acc, var(--ims-glow, #4472c4));
  text-align: center;
}

/* The card's one big object, in the same corner Scrubby sits in on Scrub In.
   Sized and placed to match him, so the nine cards read as one family: a
   silhouette you recognise before you have read anything on the screen. Takes
   the card's own accent through `currentColor` (= --mk-acc), so there is no
   per-section rule anywhere. */
.mk-mark {
  position: absolute;
  /* Tucked well into the corner and kept under half the card's width. Bolder
     and bigger than this and the object starts covering the screen it is
     supposed to be advertising — the first pass ate a grade button, a list
     total and half a companion strip. */
  right: -7%;
  bottom: -5%;
  width: 47%;
  height: auto;
  z-index: 3;
  color: var(--mk-acc, var(--ims-glow, #4472c4));
  opacity: 0.85;
  pointer-events: none;
  filter: drop-shadow(0 5px 12px rgba(0, 0, 0, 0.6));
}
/* A big mascot sitting on the card, over its screen. Anchored to the bottom
   corner and allowed to run past both edges — .hg-mock clips, so he reads as
   sitting ON the card rather than being pasted inside it, which is how Scrubby
   already behaves on the Scrub In page itself.
   The wash that keeps the board legible under him is .hg-mock::after, shared
   with the other cards' marks. */
.mk-mascot {
  position: absolute;
  /* Sits ON the bottom edge rather than through it. He bleeds a little to the
     right, where there is nothing to lose, and only a sliver off the bottom:
     the body is one big ellipse, so cropping any real amount of it leaves a
     flat orange band that reads as a rendering fault rather than as a cat
     leaning on the card. */
  right: -4%;
  bottom: -1.5%;
  width: 62%;
  z-index: 3;
  pointer-events: none;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55));
}
.mk-mascot svg { display: block; width: 100%; height: auto; }

/* Fallback for a section with no miniature written yet — its emoji, large. */
.mk-plain {
  align-items: center;
  justify-content: center;
  font-size: 3.4em;
}

/* A count on the right of a list row — Exam Edge's per-deck due totals. */
.mk-num {
  flex: 0 0 auto;
  font-size: 0.88em;
  font-weight: 700;
  color: var(--mk-acc, var(--ims-glow, #4472c4));
}
