/* ═══════════════════════════════════════════════════════════════════════
   Movember x Bunnings POC — module CSS

   Order matters: the co-brand design system first (it defines the tokens),
   then the shared engine CSS (it consumes them), then the module's own
   components and the handful of engine rules that hardcode a MiM value the
   token bridge cannot reach.
   ═══════════════════════════════════════════════════════════════════════ */
@import url('./cobrand-design-system.css');
@import url('../../../_components/mim-gp-shared.css');
@import url('../../../_components/rtl-activities.css');


/* ═══════════════════════════════════════════════════════════════════════
   0 · TOKENS THE ENGINE ALSO DECLARES ON :root — RE-DECLARED AFTER IT
   ───────────────────────────────────────────────────────────────────────
   The design system is imported FIRST so the engine can consume its tokens.
   That is right for everything the engine only READS — but mim-gp-shared.css
   opens with a :root block of its own, and for those eight names equal
   specificity means the LAST declaration wins, which is the engine's. The
   design system sets them and they silently revert.

   The visible damage before this block existed:
     · --mim-purple-aa / --mim-purple-aa-dark reverted to MiM purple, so the
       settings toggles, keypoint rules and dev badge came through purple in
       an otherwise green module — colour leaking from another brand, which no
       contrast gate can catch because it is all borders and fills.
     · --tex-* and --tex-bg reverted to MiM's photocopy URLs, so the SCORM
       package requested two texture files it does not ship and 404'd on both.
     · --header-h / --footer-h reverted to the engine's 60/68.

   Anything the design system sets that the engine does NOT declare on :root
   comes through fine and stays there. This block is only the collisions.
   ═══════════════════════════════════════════════════════════════════════ */
:root {
  --mim-purple-aa:      var(--bn-green);
  --mim-purple-aa-dark: var(--bn-green-deep);

  /* Neither brand has a texture. Off, so the surfaces render flat and the
     package stops asking for files it does not carry. */
  --tex-photocopy-black:  none;
  --tex-photocopy-white:  none;
  --tex-photocopy-purple: none;
  --tex-bg: none;

  --header-h: 64px;
  --footer-h: 72px;

  /* The engine's build-flag palette is an amber that belongs to neither
     brand. Retuned to the co-brand's green, still AA on its own fill. */
  --flag-bg:     rgba(13, 82, 87, 0.12);
  --flag-border: var(--bn-green);
  --flag-fg:     var(--bn-green-deep);
}
/* The night-mode lift for these two lives with the rest of night mode in
   section 10 — one place, not two. */


/* ═══════════════════════════════════════════════════════════════════════
   1 · ENGINE RULES THAT HARDCODE A MiM VALUE
   The token bridge reskins almost everything. These are the leftovers —
   rules where the engine bakes in a purple rgba() or assumes dark text on
   the accent. Both assumptions break on Bunnings green (black on #0D5257 is
   2.4:1), so they are corrected here rather than in the engine.
   ═══════════════════════════════════════════════════════════════════════ */

/* Accent-filled controls take white ink, not black. */
.nav-btn--ghost:hover  { background: var(--accent); color: var(--mo-white); border-color: var(--accent); }
.reflect__save         { background: var(--accent); color: var(--mo-white); }

/* Hardcoded purple tints → green tints. */
.text-size-btn.is-active,
body.night-mode .text-size-btn.is-active { background: rgba(13, 82, 87, 0.12); border-color: var(--accent); }
.cl-entry__tag--feat   { background: rgba(13, 82, 87, 0.14); color: var(--bn-green-deep); }
.changelog-access-btn  { border-color: rgba(13, 82, 87, 0.55); }

/* Anton is a tight condensed display face — the engine's -0.025em tracking
   was drawn for Lora and closes the counters up. Reset it, and let the
   display face carry its own caps. */
.title, .heading, .keypoint, .reflect__prompt {
  font-family: var(--font-feature);
  letter-spacing: 0;
  text-transform: uppercase;
}
.title   { line-height: 1.02; }
.heading { line-height: 1.06; }

/* The engine gives .screen-inner a stacking rhythm but .content-wrap none —
   MiM's Lora sits inside its line box, so nothing showed. Anton's caps
   OVERFLOW their line box at this leading, so an unspaced heading lands
   physically on top of the paragraph under it. Mirror the engine's rhythm
   onto .content-wrap and the display face gets the room it needs. */
.content-wrap > * + *           { margin-top: var(--sp-5); }
.content-wrap > .eyebrow + *    { margin-top: var(--sp-3); }
/* Reflection prompts and key points are sentences, not headlines — keep the
   display face but drop the caps, which are unreadable at paragraph length. */
.keypoint, .reflect__prompt { text-transform: none; font-family: var(--font-primary); font-weight: var(--weight-semibold); }


/* ═══════════════════════════════════════════════════════════════════════
   2 · THE CO-BRAND LOCKUP
   Movember first and larger; Bunnings second, always on its own green
   plate, always separated by a hairline. The plate is not decoration — the
   Bunnings mark is drawn to sit on green, and its "warehouse" script is
   white on red, so on any other ground it either disappears or has to be
   recoloured into something that is no longer their logo.
   ═══════════════════════════════════════════════════════════════════════ */
.cobrand { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }

/* .module-header__logo carries the engine's filter: invert(1) — the wordmark
   ships as black art on transparent, so it inverts to white on the black
   header and stays black anywhere else it is used. */
.cobrand .module-header__logo { height: 17px; }

.cobrand__rule {
  width: 1px; height: 22px; background: rgba(255,255,255,0.28); flex-shrink: 0;
}
.cobrand__plate {
  display: inline-flex; align-items: center;
  background: var(--bn-green); border-radius: 3px;
  padding: 5px 7px; flex-shrink: 0;
}
.cobrand__partner { height: 15px; width: auto; display: block; }

/* On a light ground — the brand-system screen and the closing screen — the
   same lockup, with the Movember mark left black. */
.cobrand--light .module-header__logo { filter: none; }
.cobrand--light .cobrand__rule { background: var(--mo-black-25); }
.cobrand--lg .module-header__logo { height: 30px; }
.cobrand--lg .cobrand__rule { width: 1px; height: 40px; }
.cobrand--lg .cobrand__plate { padding: 9px 12px; border-radius: 4px; }
.cobrand--lg .cobrand__partner { height: 27px; }

/* Responsive lockup. The Mo mark stands in for the wordmark on narrow screens
   — the co-brand is the last thing that should be dropped, and a 172px
   wordmark plus a plate plus four chrome buttons will not fit in 390px. */
.cobrand__mo { display: block; flex-shrink: 0; line-height: 0; }

@media (max-width: 720px) {
  .cobrand { gap: 9px; }
  .cobrand .module-header__logo { height: 15px; }
  .cobrand__rule { height: 18px; }
  .cobrand__partner { height: 12px; }
  .cobrand__plate { padding: 4px 6px; }
  /* At this width the lockup plus the chrome buttons leave nothing for the
     title, and the engine's ellipsis makes it read as a truncation bug.
     Drop it — the module name is on the landing screen and in the menu. */
  .module-header__title { display: none; }
}

@media (max-width: 560px) {
  /* <source media> has already swapped the wordmark for the Mo mark; all the
     stylesheet does is give it its own height. */
  .cobrand .module-header__logo { height: 17px; }
  .cobrand { gap: 8px; }

  /* The hero lockup keeps the full wordmark — there is width for it there —
     but it has to be allowed to wrap rather than run off the edge. */
  .cb-hero__lockup { flex-wrap: wrap; row-gap: 12px; }
  .cobrand--lg .module-header__logo { height: 22px; }
  .cobrand--lg .cobrand__rule { height: 30px; }
  .cobrand--lg .cobrand__partner { height: 20px; }
  .cobrand--lg .cobrand__plate { padding: 7px 9px; }
}


/* ═══════════════════════════════════════════════════════════════════════
   3 · LANDING — the co-branded hero
   Movember's black-first ground, one green rule, the lockup, and the
   partnership line. Bunnings appears exactly twice: the logo and the rule.
   ═══════════════════════════════════════════════════════════════════════ */
#screen-1.screen--hero.active {
  display: flex; align-items: center; justify-content: center;
  padding: 0; overflow: hidden;
  min-height: calc(100vh - var(--header-h) - var(--footer-h));
  background: var(--mo-black); color: var(--mo-white);
}
.cb-hero {
  position: relative; z-index: 2; width: 100%; box-sizing: border-box;
  padding: clamp(28px, 6vw, 72px);
  display: flex; flex-direction: column; align-items: flex-start;
  max-width: 1100px;
}
.cb-hero__lockup { margin-bottom: clamp(24px, 4vh, 48px); animation: cbRise .6s var(--ease-out) both; }
.cb-hero__rule {
  width: 72px; height: 6px; background: var(--bn-green-mid);
  margin-bottom: clamp(18px, 3vh, 32px);
  animation: cbWipe .7s var(--ease-out) 180ms both;
}
.cb-hero__title {
  font-family: var(--font-feature); text-transform: uppercase;
  font-size: calc(clamp(40px, 7.4vw, 108px) * var(--fs-scale));
  line-height: 0.94; letter-spacing: 0; color: var(--mo-white); margin: 0;
  max-width: 15ch;
}
.cb-hero__title span { display: block; }
.cb-hero__sub {
  font-family: var(--font-primary); font-weight: var(--weight-light);
  font-size: calc(clamp(17px, 2vw, 25px) * var(--fs-scale));
  line-height: 1.35; color: rgba(255,255,255,0.82);
  margin-top: clamp(16px, 2.5vh, 28px); max-width: 46ch;
  animation: cbFade .7s ease 780ms both;
}
.cb-hero__poc {
  display: inline-flex; align-items: center; gap: 10px;
  margin-top: clamp(20px, 3vh, 36px); padding: 9px 16px;
  border: 1px solid rgba(255,255,255,0.28); border-radius: 3px;
  font-family: var(--font-primary); font-weight: var(--weight-semibold);
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255,255,255,0.78);
  animation: cbFade .7s ease 1000ms both;
}
.cb-hero__poc::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--bn-red); flex-shrink: 0;
}

@keyframes cbRise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes cbWipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes cbFade { from { opacity: 0; } to { opacity: 1; } }

/* Reduced motion COMPRESSES, never removes — animation:none on an element
   revealed by an animation hides it for good. */
@media (prefers-reduced-motion: reduce) {
  .cb-hero__lockup, .cb-hero__rule, .cb-hero__sub, .cb-hero__poc,
  .cb-reveal { animation-duration: 0.01ms !important; animation-delay: 0ms !important; }
}
body.reduced-motion .cb-hero__lockup,
body.reduced-motion .cb-hero__rule,
body.reduced-motion .cb-hero__sub,
body.reduced-motion .cb-hero__poc,
body.reduced-motion .cb-reveal { animation-duration: 0.01ms !important; animation-delay: 0ms !important; }


/* ═══════════════════════════════════════════════════════════════════════
   4 · PARTNER SURFACES
   The one place Bunnings green owns the whole ground. Used sparingly: the
   brand-system screen, the "what this is for" panel, and the close.
   ═══════════════════════════════════════════════════════════════════════ */
.cb-panel {
  background: var(--bn-green); color: var(--mo-white);
  border-radius: var(--radius-lg); padding: clamp(24px, 4vw, 40px);
  max-width: var(--measure);
}
.cb-panel .cb-panel__title {
  font-family: var(--font-feature); text-transform: uppercase;
  font-size: calc(clamp(24px, 2.6vw, 34px) * var(--fs-scale));
  line-height: 1.04; color: var(--mo-white); margin: 0 0 14px;
}
.cb-panel p { color: rgba(255,255,255,0.94); font-weight: var(--weight-light); }
.cb-panel p + p { margin-top: 14px; }
.cb-panel__foot {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 24px; padding-top: 20px;
  border-top: 1px solid var(--bn-green-pale);
}
/* The panel ground IS the plate colour, so the mark sits on its native green
   directly. A plate here would be green-on-green — an invisible box. */
.cb-panel__foot .cobrand__plate { background: transparent; padding: 0; }
.cb-panel__foot .cobrand__partner { height: 22px; }

.cb-wash {
  background: var(--bn-green-wash);
  border-left: 4px solid var(--accent);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  padding: 20px 24px; max-width: var(--measure);
}
.cb-wash .cb-wash__label {
  display: block; font-family: var(--font-primary); font-weight: var(--weight-bold);
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--bn-green-deep); margin-bottom: 8px;
}

/* The single red rule. Red appears here and in the logo, nowhere else. */
.cb-emphasis {
  border-left: 4px solid var(--bn-red);
  padding-left: 20px; max-width: var(--measure);
}


/* ═══════════════════════════════════════════════════════════════════════
   5 · BRAND-SYSTEM SCREEN — swatches and the lockup rules
   ═══════════════════════════════════════════════════════════════════════ */
.cb-swatches {
  /* 160px, not 132: at the 700px measure that lands on four columns, so seven
     swatches read as 4 + 3 rather than 5 + 2 with three empty cells. */
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 2px; margin-top: var(--sp-5); max-width: var(--measure);
}
.cb-sw { padding: 16px 14px 14px; min-height: 104px; display: flex; flex-direction: column; justify-content: flex-end; }
.cb-sw__name { font-family: var(--font-primary); font-weight: var(--weight-bold); font-size: 12px; letter-spacing: 0.02em; }
.cb-sw__hex  { font-family: var(--font-mono); font-size: 11px; opacity: 0.75; margin-top: 3px; }
.cb-sw__role { font-family: var(--font-primary); font-size: 11px; line-height: 1.3; margin-top: 6px; opacity: 0.75; }
.cb-sw--black { background: var(--mo-black);      color: var(--mo-white); }
.cb-sw--white { background: var(--mo-white);      color: var(--mo-black); box-shadow: inset 0 0 0 1px var(--mo-black-15); }
.cb-sw--grey  { background: var(--mo-grey);       color: var(--mo-white); }
.cb-sw--green { background: var(--bn-green);      color: var(--mo-white); }
.cb-sw--deep  { background: var(--bn-green-deep); color: var(--mo-white); }
.cb-sw--wash  { background: var(--bn-green-wash); color: var(--bn-green-deep); }
.cb-sw--red   { background: var(--bn-red);        color: var(--mo-white); }

.cb-rules { list-style: none; margin: var(--sp-5) 0 0; padding: 0; max-width: var(--measure); }
.cb-rules li {
  position: relative; padding: 12px 0 12px 34px;
  border-top: 1px solid var(--border);
  font-family: var(--font-primary); font-weight: var(--weight-light);
  font-size: calc(15px * var(--fs-scale)); line-height: 1.5; color: var(--fg);
}
.cb-rules li:last-child { border-bottom: 1px solid var(--border); }
.cb-rules li strong { font-weight: var(--weight-bold); }
.cb-rules li::before {
  content: ""; position: absolute; left: 0; top: 19px;
  width: 18px; height: 3px; background: var(--accent);
}
.cb-rules li.cb-rules__no::before { background: var(--bn-red); }


/* ═══════════════════════════════════════════════════════════════════════
   6 · BIG STAT — Anton at scale, the Movember way
   ═══════════════════════════════════════════════════════════════════════ */
.cb-stat {
  display: flex; align-items: baseline; gap: 20px; flex-wrap: wrap;
  max-width: var(--measure); margin-top: var(--sp-5);
}
.cb-stat__figure {
  font-family: var(--font-feature); text-transform: uppercase;
  font-size: calc(clamp(64px, 11vw, 132px) * var(--fs-scale));
  line-height: 0.86; color: var(--accent); letter-spacing: 0;
}
.cb-stat__sentence {
  font-family: var(--font-primary); font-weight: var(--weight-light);
  font-size: calc(18px * var(--fs-scale)); line-height: 1.4;
  max-width: 24ch; color: var(--fg); flex: 1 1 220px;
}
.cb-stat__source {
  font-family: var(--font-primary); font-size: 12px; line-height: 1.45;
  color: var(--fg-subtle); margin-top: 14px; max-width: var(--measure);
}
.screen--dark .cb-stat__figure { color: var(--mo-white); }
.screen--dark .cb-stat__sentence { color: rgba(255,255,255,0.92); }
.screen--dark .cb-stat__source { color: rgba(255,255,255,0.62); }


/* ═══════════════════════════════════════════════════════════════════════
   7 · FEATURE GRID — what the engine gives you for free
   ═══════════════════════════════════════════════════════════════════════ */
.cb-feats {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 2px; margin-top: var(--sp-5); background: var(--border); border: 1px solid var(--border);
}
.cb-feat { display: flex; gap: 14px; padding: 20px 18px; background: var(--mo-white); }
.cb-feat__icon { flex: 0 0 auto; width: 30px; height: 30px; color: var(--accent); }
.cb-feat__icon svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.8; }
.cb-feat__title {
  font-family: var(--font-primary); font-weight: var(--weight-bold);
  font-size: calc(15px * var(--fs-scale)); line-height: 1.25; margin: 2px 0 5px; color: var(--fg);
}
.cb-feat__desc { font-family: var(--font-primary); font-weight: var(--weight-light); font-size: calc(13px * var(--fs-scale)); line-height: 1.5; color: var(--fg-muted); margin: 0; }
body.night-mode .cb-feat { background: #17171b; }
body.night-mode .cb-feat__title { color: rgba(255,255,255,0.95); }
body.night-mode .cb-feat__desc  { color: rgba(255,255,255,0.72); }
@media (max-width: 720px) { .cb-feats { grid-template-columns: 1fr; } }


/* ═══════════════════════════════════════════════════════════════════════
   8 · ALEC — Movember's conversation framework, as a lettered rail
   ═══════════════════════════════════════════════════════════════════════ */
.cb-alec { display: grid; gap: 2px; margin-top: var(--sp-5); max-width: var(--measure); }
.cb-alec__row { display: flex; gap: 18px; align-items: flex-start; padding: 18px 20px; background: var(--mo-black-04); }
.cb-alec__letter {
  flex: 0 0 auto; width: 46px; height: 46px; display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--mo-white);
  font-family: var(--font-feature); font-size: calc(26px * var(--fs-scale)); line-height: 1;
  padding-top: 3px; box-sizing: border-box;
}
.cb-alec__name { font-family: var(--font-primary); font-weight: var(--weight-bold); font-size: calc(15px * var(--fs-scale)); margin: 4px 0 4px; color: var(--fg); }
.cb-alec__what { font-family: var(--font-primary); font-weight: var(--weight-light); font-size: calc(14px * var(--fs-scale)); line-height: 1.5; color: var(--fg-muted); margin: 0; }
body.night-mode .cb-alec__row { background: rgba(255,255,255,0.06); }
body.night-mode .cb-alec__name { color: rgba(255,255,255,0.95); }
body.night-mode .cb-alec__what { color: rgba(255,255,255,0.72); }


/* ═══════════════════════════════════════════════════════════════════════
   9 · CLOSING SCREEN
   ═══════════════════════════════════════════════════════════════════════ */
.cb-close__links { list-style: none; margin: var(--sp-5) 0 0; padding: 0; max-width: var(--measure); }
.cb-close__links li { border-top: 1px solid var(--border); padding: 14px 0; }
.cb-close__links li:last-child { border-bottom: 1px solid var(--border); }
.cb-close__links a { font-family: var(--font-primary); font-weight: var(--weight-semibold); font-size: calc(15px * var(--fs-scale)); }
.cb-close__links span { display: block; font-family: var(--font-primary); font-weight: var(--weight-light); font-size: calc(13px * var(--fs-scale)); color: var(--fg-muted); margin-top: 3px; }
body.night-mode .cb-close__links span { color: rgba(255,255,255,0.7); }


/* ═══════════════════════════════════════════════════════════════════════
   10 · NIGHT MODE
   The engine does not redefine --fg in night mode, so anything that reads
   var(--fg) needs an explicit body.night-mode rule. Bunnings green at
   #0D5257 is too dark to carry text on a near-black ground — night mode
   lifts the accent to a tint of the same hue rather than dropping it.
   ═══════════════════════════════════════════════════════════════════════ */
body.night-mode {
  /* --bn-* stay brand-true at every setting — a swatch that changes colour in
     night mode is no longer showing the brand. Only the UI accent lifts:
     #0D5257 on the engine's #0b0b0d ground is 1.4:1, effectively invisible.
     #7FC3C7 is the same hue carried up to ~9:1 on that ground. */
  --accent:             #7FC3C7;
  --accent-deep:        #A6D9DC;
  --mim-purple:         #7FC3C7;
  --mim-purple-aa:      #7FC3C7;
  --mim-purple-aa-dark: #7FC3C7;
  --mim-purple-soft:    rgba(127,195,199,0.22);
  --bg-surface:   #17171b;
  --bg-mid:       #1f1f25;
  --text-primary: rgba(255,255,255,0.95);
  --text-muted:   rgba(255,255,255,0.72);
  --border:       rgba(255,255,255,0.16);
  --fg-muted:     rgba(255,255,255,0.80);
  --fg-subtle:    rgba(255,255,255,0.66);
  /* The activity library's correct/incorrect pair is drawn for a white ground
     — #1F7A52 lands at 2.5:1 on the night surface, which is the sequence
     number and the scenario's trust delta gone. Lift both to the same hues at
     AA on dark. They stay a PAIR of hues, never the only signal: every state
     the library draws also carries a mark or a word. */
  --success: #4CC38A;
  --error:   #F08A6B;
}
/* Accent-filled controls flip to dark ink once the accent is a light tint. */
body.night-mode .nav-btn--ghost:hover,
body.night-mode .reflect__save,
body.night-mode .cb-alec__letter,
body.night-mode .rtl-act__btn:not(.rtl-act__btn--ghost) { color: #0E2426; }
body.night-mode .cb-wash { background: rgba(127,195,199,0.12); }
body.night-mode .cb-wash .cb-wash__label { color: #9FD6D9; }
body.night-mode .cb-rules li { color: rgba(255,255,255,0.9); }
body.night-mode .cb-close__links a { color: #7FC3C7; }
body.night-mode .cb-alec__row { background: rgba(255,255,255,0.06); }
body.night-mode .cb-alec__name { color: rgba(255,255,255,0.95); }
body.night-mode .cb-alec__what { color: rgba(255,255,255,0.72); }
body.night-mode .cb-feat { background: #17171b; }
body.night-mode .cb-feat__title { color: rgba(255,255,255,0.95); }
body.night-mode .cb-feat__desc  { color: rgba(255,255,255,0.72); }
body.night-mode .cb-close__links span { color: rgba(255,255,255,0.7); }
/* The swatch grid and the logo plate are brand artefacts, not chrome — they
   render identically in both modes, so the white swatch keeps black ink. */
body.night-mode .cb-sw--white { background: var(--mo-white); color: var(--mo-black); }


/* ═══════════════════════════════════════════════════════════════════════
   12 · HEADER CONTROLS — sound, and the live brand swap
   The engine builds .module-header__right and never re-renders it, so two
   more .btn-icon buttons can sit alongside its own without a fight. They
   deliberately reuse .btn-icon rather than inventing a control: the point
   of the demo is that partner work is a stylesheet, and a bespoke button
   would quietly contradict it.

   NOT .module-header__logo. That class is the toolchain's handle for the
   7-click dev-mode gesture and Playwright's strict mode throws on a second
   match — see the note at the top of index.html.
   ═══════════════════════════════════════════════════════════════════════ */

/* Sound off is shown by a slash drawn over the speaker, not by colour
   alone: at 390px this button is 12px of glyph and a tint is unreadable. */
#sfxToggle .cb-sfx__slash { opacity: 0; transition: opacity var(--dur-fast) linear; }
html[data-sfx="off"] #sfxToggle .cb-sfx__slash { opacity: 1; }
html[data-sfx="off"] #sfxToggle .cb-sfx__wave  { opacity: 0.25; }

/* The brand-swap button carries the partner green while the partner brand
   is on, and drops to the header ink when it is off — so the control
   states what it is about to do. */
#brandSwap {
  width: auto; padding: 0 10px; gap: 0;
  font-family: var(--font-primary); font-weight: var(--weight-bold);
  font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
  white-space: nowrap;
}
#brandSwap .cb-swap__dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--bn-green-mid); margin-right: 7px; vertical-align: middle;
  transition: background var(--dur-base) linear;
}
html[data-brand="mo"] #brandSwap .cb-swap__dot { background: rgba(255,255,255,0.45); }

@media (max-width: 860px) {
  #brandSwap .cb-swap__label { display: none; }
  #brandSwap { padding: 0 9px; }
}


/* ═══════════════════════════════════════════════════════════════════════
   13 · HERO — the partner wash
   A single green sweep behind the lockup, ONE SHOT, not a loop. An infinite
   background animation on a landing screen costs 10-18% of a core for as
   long as the screen is open, which on a pitch laptop driving a projector is
   the difference between smooth and not. It plays once and it stops.
   ═══════════════════════════════════════════════════════════════════════ */
.cb-hero__wash { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.cb-hero__wash::before {
  content: ""; position: absolute; top: -30%; right: -18%;
  width: 78vw; height: 160%;
  background: radial-gradient(closest-side, rgba(13,82,87,0.85), rgba(13,82,87,0) 72%);
  transform: translateX(12%);
  animation: cbWash 1.5s var(--ease-out) 120ms both;
}
/* One hairline of Bunnings red — the single place red is allowed to be
   decorative. It is 2px and it carries no meaning. */
.cb-hero__wash::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  background: linear-gradient(90deg, var(--bn-red) 0%, var(--bn-red) 22%, transparent 22%);
  animation: cbWipe 1.1s var(--ease-out) 700ms both;
}
@keyframes cbWash {
  from { opacity: 0; transform: translateX(26%) scale(0.92); }
  to   { opacity: 1; transform: translateX(12%) scale(1); }
}

html[data-brand="mo"] .cb-hero__wash::before {
  background: radial-gradient(closest-side, rgba(93,94,100,0.55), rgba(93,94,100,0) 72%);
}
html[data-brand="mo"] .cb-hero__wash::after { display: none; }

@media (prefers-reduced-motion: reduce) {
  .cb-hero__wash::before,
  .cb-hero__wash::after { animation-duration: 0.01ms !important; animation-delay: 0ms !important; }
}
body.reduced-motion .cb-hero__wash::before,
body.reduced-motion .cb-hero__wash::after { animation-duration: 0.01ms !important; animation-delay: 0ms !important; }


/* ═══════════════════════════════════════════════════════════════════════
   14 · THE HAMMER DEVICE
   The Bunnings hammer-in-circle, used as a section mark. It is set to
   currentColor, so it takes the ink of whatever it sits on — and it only
   ever sits on a green ground (white) or a light ground (red), which are
   the two colours the mark is actually drawn in. In Movember-only mode it
   is hidden outright rather than greyed: a desaturated partner logo is
   still their logo, used wrongly.
   ═══════════════════════════════════════════════════════════════════════ */
.cb-hammer { display: inline-block; width: 28px; height: 28px; flex-shrink: 0; line-height: 0; }
.cb-hammer svg { width: 100%; height: 100%; display: block; }
.cb-hammer--red   { color: var(--bn-red); }
.cb-hammer--white { color: var(--mo-white); }
.cb-hammer--lg    { width: 46px; height: 46px; }


/* ═══════════════════════════════════════════════════════════════════════
   15 · VIDEO — click-to-play facade
   A bare YouTube iframe is the wrong call twice over. It fails with Error
   153 from file:// and inside an LMS iframe, because the embed is
   referrer-gated; and it loads the whole YouTube player on every screen
   change whether or not anyone watches. A poster plus a play button costs
   nothing until it is clicked, then replaces itself with the real iframe.

   Navigation is NEVER gated on watching this. It is illustration.
   ═══════════════════════════════════════════════════════════════════════ */
.cb-video {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  background: var(--mo-black); border-radius: var(--radius-md);
  overflow: hidden; border: 1px solid var(--border-subtle);
}
.cb-video__poster {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
  /* Solid base FIRST, gradient over it — same reason as the sizzle panel
     below: a bare gradient computes to a transparent background-color, so
     nothing downstream can verify the ink sitting on it. */
  background-color: var(--bn-green-deep);
  background-image: linear-gradient(135deg, var(--bn-green-deep) 0%, var(--bn-green) 62%, #0A3E42 100%);
  border: 0; cursor: pointer; color: var(--mo-white); padding: 24px; text-align: center;
}
html[data-brand="mo"] .cb-video__poster {
  background-color: #101010;
  background-image: linear-gradient(135deg, #1A1A1A 0%, #000 100%);
}
.cb-video__poster:hover .cb-video__play { transform: scale(1.06); background: var(--mo-white); color: var(--bn-green); }
.cb-video__play {
  width: 72px; height: 72px; border-radius: 50%;
  background: rgba(255,255,255,0.14); border: 2px solid var(--mo-white); color: var(--mo-white);
  display: flex; align-items: center; justify-content: center;
  transition: transform var(--dur-base) var(--ease-out), background var(--dur-base) linear, color var(--dur-base) linear;
}
.cb-video__play svg { width: 26px; height: 26px; margin-left: 4px; }
.cb-video__label {
  font-family: var(--font-primary); font-weight: var(--weight-semibold);
  font-size: calc(15px * var(--fs-scale)); line-height: 1.4; max-width: 40ch;
  color: rgba(255,255,255,0.95);
}
.cb-video__meta {
  font-family: var(--font-primary); font-weight: var(--weight-bold);
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255,255,255,0.72);
}
.cb-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.cb-video__note { margin-top: 10px; font-size: calc(13px * var(--fs-scale)); color: var(--fg-subtle); line-height: 1.5; }
@media (prefers-reduced-motion: reduce) { .cb-video__play { transition: none; } }


/* ═══════════════════════════════════════════════════════════════════════
   16 · THE SIZZLE
   The sausage sizzle is the most recognisable thing Bunnings does that has
   nothing to do with hardware, and it is already a fundraising surface —
   which makes it the one place the two brands have a real existing overlap
   rather than a logo sitting next to a logo.
   ═══════════════════════════════════════════════════════════════════════ */
.cb-sizzle {
  /* Three SOLID grounds, declared as scoped tokens.

     The first cut of this panel was a gradient with rgba() cards on top of
     it, and the contrast gate reported six failures at a ratio of exactly
     1.0 — which is the giveaway. A gradient leaves computed
     background-color transparent, and an rgba() card is opaque enough to
     stop a checker walking up the tree but is not a colour it can composite
     against, so it resolves white and reads white-on-white. That is not a
     false positive: a colour no tool can resolve is a colour nobody can
     verify, and it is also what the browser paints if the gradient fails.

     --sz-raised is 10% white over the ground and --sz-sunk is 22% black over
     it. Same appearance, stated rather than composited — and they follow the
     brand swap instead of staying green on a black panel. */
  --sz-ground: var(--bn-green);
  --sz-raised: #256368;
  --sz-sunk:   #0A4044;

  background-color: var(--sz-ground);
  background-image: linear-gradient(160deg, rgba(255,255,255,0.04) 0%, rgba(0,0,0,0.16) 100%);
  color: var(--mo-white); border-radius: var(--radius-lg);
  padding: clamp(26px, 4vw, 44px); position: relative; overflow: hidden;
}
html[data-brand="mo"] .cb-sizzle {
  --sz-ground: #101010;
  --sz-raised: #262626;
  --sz-sunk:   #000000;
}
.cb-sizzle__head { display: flex; align-items: center; gap: 16px; margin-bottom: 18px; }
.cb-sizzle__title {
  font-family: var(--font-feature); text-transform: uppercase; margin: 0;
  font-size: calc(clamp(26px, 3.4vw, 40px) * var(--fs-scale));
  line-height: 1.02; color: var(--mo-white);
}
.cb-sizzle p { color: rgba(255,255,255,0.92); font-weight: var(--weight-light); max-width: 58ch; }
.cb-sizzle p + p { margin-top: 14px; }

.cb-sizzle__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px; margin-top: 26px;
}
.cb-sizzle__stat {
  background: var(--sz-raised); border: 1px solid rgba(255,255,255,0.18);
  border-radius: var(--radius-md); padding: 18px 16px;
}
.cb-sizzle__n {
  font-family: var(--font-feature); font-size: calc(clamp(30px, 3.6vw, 44px) * var(--fs-scale));
  line-height: 1; color: var(--mo-white); display: block;
}
.cb-sizzle__k {
  display: block; margin-top: 8px;
  font-size: calc(13px * var(--fs-scale)); line-height: 1.45;
  color: rgba(255,255,255,0.86); font-weight: var(--weight-light);
}
/* Every figure on this screen is invented. It says so in the same box as the
   figures, not in a footnote three scrolls away. */
.cb-sizzle__caveat {
  margin-top: 20px; padding: 12px 14px;
  border-left: 3px solid var(--bn-red); background: var(--sz-sunk);
  font-size: calc(13px * var(--fs-scale)); line-height: 1.5;
  color: rgba(255,255,255,0.9); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
html[data-brand="mo"] .cb-sizzle__caveat { border-left-color: var(--mo-white); }

/* The listen button. The sound is synthesised on the spot, so this is a demo
   of the audio engine as much as it is a joke. */
.cb-sizzle__listen {
  margin-top: 24px; display: inline-flex; align-items: center; gap: 11px;
  padding: 12px 20px; border-radius: var(--radius-pill);
  background: var(--mo-white); color: var(--bn-green-deep); border: 0; cursor: pointer;
  font-family: var(--font-primary); font-weight: var(--weight-bold);
  font-size: calc(14px * var(--fs-scale)); letter-spacing: 0.04em;
  transition: transform var(--dur-fast) var(--ease-out);
}
.cb-sizzle__listen:hover { transform: translateY(-1px); }
.cb-sizzle__listen svg { width: 17px; height: 17px; }
html[data-brand="mo"] .cb-sizzle__listen { color: var(--mo-black); }
@media (prefers-reduced-motion: reduce) {
  .cb-sizzle__listen { transition: none; }
  .cb-sizzle__listen:hover { transform: none; }
}


/* ═══════════════════════════════════════════════════════════════════════
   17 · PARTNER STRIP — a green band that carries the mark
   Used where the module is talking ABOUT the partnership rather than about
   the content. Gives Bunnings a second and third surface without letting
   the logo drift onto grounds it is not drawn for.
   ═══════════════════════════════════════════════════════════════════════ */
.cb-strip {
  display: flex; align-items: center; gap: clamp(14px, 2vw, 24px); flex-wrap: wrap;
  background: var(--bn-green); color: var(--mo-white);
  border-radius: var(--radius-md); padding: 18px clamp(18px, 2.4vw, 28px);
}
html[data-brand="mo"] .cb-strip { background: var(--mo-black); }
.cb-strip__mark { height: 24px; width: auto; display: block; flex-shrink: 0; }
.cb-strip__text {
  font-family: var(--font-primary); font-weight: var(--weight-light);
  font-size: calc(15px * var(--fs-scale)); line-height: 1.5;
  color: rgba(255,255,255,0.94); margin: 0; max-width: 62ch;
}
.cb-strip__text strong { font-weight: var(--weight-bold); color: var(--mo-white); }


/* ═══════════════════════════════════════════════════════════════════════
   18 · SWAP CALLOUT — the control explained where it is demonstrated
   ═══════════════════════════════════════════════════════════════════════ */
.cb-swapdemo {
  border: 2px dashed var(--bn-green); border-radius: var(--radius-md);
  padding: 20px clamp(18px, 2.4vw, 26px); background: var(--bn-green-wash);
}
html[data-brand="mo"] .cb-swapdemo { border-color: var(--mo-black-25); background: var(--mo-black-04); }
.cb-swapdemo__title {
  font-family: var(--font-primary); font-weight: var(--weight-bold);
  font-size: calc(15px * var(--fs-scale)); color: var(--text-strong);
  margin: 0 0 8px; display: flex; align-items: center; gap: 10px;
}
.cb-swapdemo p { font-size: calc(15px * var(--fs-scale)); line-height: 1.55; color: var(--fg-muted); }
.cb-swapdemo__btn {
  margin-top: 14px; display: inline-flex; align-items: center; gap: 10px;
  padding: 11px 18px; border-radius: var(--radius-sm);
  /* A CONTROL, so it takes --accent, which night mode lifts to a tint.
     --bn-green stays brand-true at every setting by design, and dark ink on
     brand-true green is 1.8:1 on a night ground. */
  background: var(--accent); color: var(--mo-white); border: 0; cursor: pointer;
  font-family: var(--font-primary); font-weight: var(--weight-bold);
  font-size: calc(14px * var(--fs-scale));
}
html[data-brand="mo"] .cb-swapdemo__btn { background: var(--mo-black); }
body.night-mode .cb-swapdemo { background: #17171b; border-color: var(--accent); }
/* Joins the accent-filled-control rule in section 10: once the accent is a
   light tint the ink on it has to go dark — except in Movember-only mode,
   where the button is black and the ink stays white. */
body.night-mode .cb-swapdemo__btn { color: #0E2426; }
html[data-brand="mo"] body.night-mode .cb-swapdemo__btn { color: var(--mo-white); }


/* ═══════════════════════════════════════════════════════════════════════
   19 · ACCORDION — the FAQ on screen 3
   -------------------------------------------------------------------------
   Ported from `Men in Mind/MIM Pro/MIM Pro for GPs Part 1/module.css`
   (its [accordion] block) so this FAQ reads exactly like the MIM one, with
   its own copy.

   WHY THIS WAS MISSING. The accordion looks like engine furniture and is
   not. `mim-gp-shared.css` mentions it only in a comment; the only thing the
   engine actually supplies is the behaviour — `toggleAccordion()` toggling
   `.open` on `.accordion__item` and maintaining `aria-expanded`. Every MIM
   module carries its own copy of these fourteen lines. This module copied
   the markup and inherited the handler, so it toggled a class that nothing
   styled: no rules, no dividers, and — because the collapsed state IS
   `display: none` and there was no rule to supply it — every answer on
   screen at once.

   It renders co-branded with no extra work: every value below is a token the
   design system already binds, so --border-strong, --fg and --fg-muted come
   through green-and-black here and lift correctly in night mode.

   Nothing here is scoped to `.rtl-act`, so it is unrelated to the blanket
   `[hidden]` fix in the activity library.
   ═══════════════════════════════════════════════════════════════════════ */
.accordion {
  border-top: 1px solid var(--border-strong);
  border-bottom: 1px solid var(--border-strong);
  max-width: var(--measure);
}
.accordion__item { border-bottom: 1px solid var(--border); }
.accordion__item:last-child { border-bottom: none; }
.accordion__summary {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 22px 4px; width: 100%; background: none; border: none; cursor: pointer; text-align: left;
}
.accordion__title {
  font-family: var(--font-primary); font-weight: var(--weight-semibold);
  font-size: calc(17px * var(--fs-scale)); line-height: 1.3; color: var(--fg);
}
.accordion__toggle {
  font-family: var(--font-primary); font-size: 22px; color: var(--fg-muted);
  line-height: 1; transition: transform 220ms var(--ease-standard); flex-shrink: 0;
}
.accordion__item.open .accordion__toggle { transform: rotate(45deg); }
.accordion__body { display: none; padding: 0 4px 24px; }
.accordion__item.open .accordion__body { display: block; }
.accordion__body .body {
  font-family: var(--font-primary); font-weight: var(--weight-light);
  font-size: calc(16px * var(--fs-scale)); line-height: 1.6; max-width: 62ch;
}
.accordion__body .body + .body { margin-top: 12px; }

/* The "+" rotating to "×" is decoration on a state that is also carried by
   aria-expanded and by the body appearing, so reduced motion can drop it
   outright without losing information. */
@media (prefers-reduced-motion: reduce) { .accordion__toggle { transition: none; } }
body.reduced-motion .accordion__toggle { transition: none; }

/* The engine's focus-visible list (mim-gp-shared.css) does NOT include
   .accordion__summary — each MIM module adds it locally, alongside its copy
   of the component. Same rule, same ring, so a keyboard user gets the same
   treatment here as on every other control in the module. */
.accordion__summary:focus-visible {
  outline: 3px solid var(--mim-purple-aa-dark);
  outline-offset: 2px;
}

/* Night mode. These four live 750 lines away from the component block in the
   MIM module they were ported from, and missing them is why the first cut of
   this section landed .accordion__title at 1.07:1 in night mode.

   The cause is stated in section 10: the engine does NOT redefine --fg in
   night mode, so every rule reading var(--fg) needs an explicit night rule.
   The rest of the block reads --border, --border-strong and --fg-muted, which
   ARE redefined, which is why only the title failed. Porting a component
   means porting its night rules too, and they are not next to it. */
body.night-mode .accordion         { border-color: rgba(255,255,255,0.20); }
body.night-mode .accordion__item   { border-color: rgba(255,255,255,0.12); }
body.night-mode .accordion__title  { color: rgba(255,255,255,0.92); }
body.night-mode .accordion__toggle { color: rgba(255,255,255,0.70); }


/* ═══════════════════════════════════════════════════════════════════════
   20 · NAV TUTORIAL — screen 2
   -------------------------------------------------------------------------
   Same omission as the accordion in section 19, and worse to look at.
   `.tutorial-step` is in the engine's focus-visible list, so it LOOKS like
   engine furniture, but the component itself is carried per-module: MIM Pro
   for GPs Part 1 has seven rules for it and this module had none. With no
   `.tutorial-step__icon` box the inline chevron SVG had no width to obey and
   expanded to fill the row, one 600px arrow per step.

   Ported from that module, with the two MiM purple literals it hardcodes
   re-pointed — the same correction section 1 makes for the engine's own
   hardcoded purples. They are written as rgba(var(--mim-purple-rgb), a)
   rather than as a green literal so they follow the brand swap; the raw
   green literals elsewhere in this file predate the swap and stay green in
   Movember-only mode.

   `.tutorial-step__icon--text` (the "?" step) is deliberately left with no
   rule of its own — it has none in MIM either. The base .tutorial-step__icon
   already sets a font-size, which is all the text variant needs.
   ═══════════════════════════════════════════════════════════════════════ */
.nav-tutorial { margin-top: var(--sp-5); max-width: 720px; }
.tutorial-step {
  display: flex; align-items: flex-start; gap: 18px; width: 100%; text-align: left;
  padding: 20px 22px; margin-bottom: 14px;
  background: var(--mim-grey-light); border: 2px solid var(--border); border-radius: var(--radius-lg);
  cursor: pointer; font-family: inherit;
  transition: border-color var(--dur-base) var(--ease-standard),
              background var(--dur-base) var(--ease-standard),
              transform var(--dur-base) var(--ease-standard);
}
.tutorial-step:hover {
  border-color: var(--mim-purple);
  background: rgba(var(--mim-purple-rgb), 0.10);
  transform: translateY(-1px);
}
.tutorial-step__icon {
  flex-shrink: 0; width: 48px; height: 48px; border-radius: var(--radius-md);
  background: rgba(var(--mim-purple-rgb), 0.12); border: 1px solid var(--mim-purple);
  display: flex; align-items: center; justify-content: center;
  color: var(--mim-purple-aa-dark);
  font-family: var(--font-primary); font-weight: var(--weight-semibold); font-size: 18px;
}
.tutorial-step__icon svg { width: 22px; height: 22px; }
.tutorial-step__body { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.tutorial-step__title { font-family: var(--font-feature); font-size: calc(18px * var(--fs-scale)); color: var(--fg); }
.tutorial-step__text {
  font-family: var(--font-primary); font-weight: var(--weight-light);
  font-size: calc(14px * var(--fs-scale)); line-height: 1.55; color: var(--fg-muted);
}
body.night-mode .tutorial-step { background: #17171b; }
body.night-mode .tutorial-step__title { color: rgba(255,255,255,0.92); }
body.night-mode .tutorial-step__text { color: rgba(255,255,255,0.7); }

@media (max-width: 640px) { .tutorial-step { flex-direction: column; gap: 12px; } }
@media (prefers-reduced-motion: reduce) {
  .tutorial-step { transition: none; }
  .tutorial-step:hover { transform: none; }
}
body.reduced-motion .tutorial-step { transition: none; }
body.reduced-motion .tutorial-step:hover { transform: none; }


/* ═══════════════════════════════════════════════════════════════════════
   21 · .visually-hidden
   The engine's own name for this is `.sr-only`, and that is the only one it
   defines. One label on the estimate activity (screen 9) was written with
   `.visually-hidden` instead, so it had no rule at all and was rendering on
   screen as body copy — a screen-reader label sitting visibly above the
   input it describes.

   Defining the alias is the right fix rather than renaming the class: the
   activity library markup is shared, and the next component copied in from
   anywhere else will use whichever name its author reached for.
   ═══════════════════════════════════════════════════════════════════════ */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}


/* ═══════════════════════════════════════════════════════════════════════
   22 · THE LAST OF THE MiM PURPLE
   -------------------------------------------------------------------------
   Section 1 caught the engine's hardcoded purples that show on a first pass.
   These are the ones that only appear once something moves.

   The visible one was the button pulse. `.btn-tutorial-hl` is what the nav
   tutorial on screen 2 puts on the Continue button, and while its OUTLINE
   reads var(--mim-purple) — bridged, so already green — the glow around it
   is baked into the @keyframes as a raw rgba(183,163,252,…). A keyframe
   cannot read a token it was not written to read, so the only fix is to
   redefine the animation. Same name, declared after the @import, so this
   definition is the one that wins.
   ═══════════════════════════════════════════════════════════════════════ */
@keyframes tut-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--mim-purple-rgb), 0); }
  50%      { box-shadow: 0 0 0 8px rgba(var(--mim-purple-rgb), 0.35); }
}
@keyframes tut-pulse-large {
  0%   { box-shadow: 0 0 0 0 rgba(var(--mim-purple-rgb), 0.9); }
  45%  { box-shadow: 0 0 0 24px rgba(var(--mim-purple-rgb), 0.32); }
  75%  { box-shadow: 0 0 0 40px rgba(var(--mim-purple-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--mim-purple-rgb), 0); }
}

/* The rest of the raw purple tints in the engine, re-pointed. All are
   backgrounds and borders, which is why no contrast gate ever saw them. */
.chapter-item.active,
body.night-mode .chapter-item.active { background: rgba(var(--mim-purple-rgb), 0.14); }
.reflect__toggle:hover               { background: rgba(var(--mim-purple-rgb), 0.14); }
.flipcard__back {
  background: rgba(var(--mim-purple-rgb), 0.12);
  border-color: rgba(var(--mim-purple-rgb), 0.30);
}
/* Section 1 already re-points these three, but as green LITERALS, which do
   not follow the brand swap. Restated against the token so they do. */
.text-size-btn.is-active,
body.night-mode .text-size-btn.is-active { background: rgba(var(--mim-purple-rgb), 0.12); }
.cl-entry__tag--feat  { background: rgba(var(--mim-purple-rgb), 0.16); }
.changelog-access-btn { border-color: rgba(var(--mim-purple-rgb), 0.55); }


/* ═══════════════════════════════════════════════════════════════════════
   23 · THE HERO HAMMER
   -------------------------------------------------------------------------
   Swings on a constant loop, beside the title.

   One element, one transform, and nothing else animating — a rotation is
   compositor-only, so this costs a fraction of what the twelve-layer version
   of the same idea would. transform-origin sits low and right of centre,
   roughly where a hand would hold it, so the badge pivots like a hammer
   rather than spinning like a coin.

   Reduced motion parks it at rest rather than hiding it; it is a brand mark
   as much as an animation.
   ═══════════════════════════════════════════════════════════════════════ */
.cb-hero__row { display: flex; align-items: center; gap: clamp(14px, 2.4vw, 34px); }
.cb-hero__hammer {
  flex-shrink: 0; line-height: 0; display: block;
  width: clamp(64px, 9vw, 132px);
}
.cb-hero__hammer img {
  width: 100%; height: auto; display: block;
  transform-origin: 62% 78%;
  animation: cbSwing 1.6s ease-in-out infinite alternate;
}
@keyframes cbSwing {
  from { transform: rotate(-26deg); }
  to   { transform: rotate(12deg); }
}
@media (prefers-reduced-motion: reduce) {
  .cb-hero__hammer img { animation: none; transform: rotate(-8deg); }
}
body.reduced-motion .cb-hero__hammer img { animation: none; transform: rotate(-8deg); }

@media (max-width: 620px) {
  .cb-hero__row { gap: 12px; }
  .cb-hero__hammer { width: 54px; }
}


/* ═══════════════════════════════════════════════════════════════════════
   24 · THE ANVIL — a hammer either side of the swipe deck (screen 12)
   -------------------------------------------------------------------------
   Each one slams when the learner sorts a card to that side. The right-hand
   mark is the same file mirrored, so both heads face the deck; the mirror is
   on the <img> and the slam rotation is on the wrapper, because putting both
   transforms on one element means the flip has to be repeated inside every
   keyframe or it is lost the moment the animation starts.

   .cb-anvil wraps the activity rather than sitting inside it: the activity
   root belongs to the library, which rebuilds its own children.

   Hidden below 900px. There is no room for them beside the deck on a phone,
   and the activity gate runs at 390x844 — a decoration that overlaps the
   sort buttons at that width would break a real interaction.
   ═══════════════════════════════════════════════════════════════════════ */
.cb-anvil { position: relative; }
.cb-anvil__hammer {
  position: absolute; top: 42%; z-index: 3;
  width: clamp(60px, 7vw, 96px); line-height: 0; pointer-events: none;
  transform: rotate(-30deg);
  transition: transform 420ms cubic-bezier(0.16, 1, 0.3, 1);
}
.cb-anvil__hammer img { width: 100%; height: auto; display: block; }
.cb-anvil__hammer--left  { left:  -8%; }
.cb-anvil__hammer--right { right: -8%; transform: rotate(30deg); }
.cb-anvil__hammer--right img { transform: scaleX(-1); }

/* The slam. A short, hard rotation with a small bounce out of it — driven by
   a class the demo script adds, not by :hover, because the trigger is the
   learner sorting a card and that can come from a button, a drag or a key. */
.cb-anvil__hammer.is-slam        { animation: cbSlamL 460ms cubic-bezier(0.3, 0, 0.2, 1); }
.cb-anvil__hammer--right.is-slam { animation: cbSlamR 460ms cubic-bezier(0.3, 0, 0.2, 1); }
@keyframes cbSlamL {
  0%   { transform: rotate(-30deg); }
  38%  { transform: rotate(26deg); }
  58%  { transform: rotate(14deg); }
  100% { transform: rotate(-30deg); }
}
@keyframes cbSlamR {
  0%   { transform: rotate(30deg); }
  38%  { transform: rotate(-26deg); }
  58%  { transform: rotate(-14deg); }
  100% { transform: rotate(30deg); }
}
@media (prefers-reduced-motion: reduce) {
  .cb-anvil__hammer { transition: none; }
  .cb-anvil__hammer.is-slam, .cb-anvil__hammer--right.is-slam { animation: none; }
}
body.reduced-motion .cb-anvil__hammer.is-slam,
body.reduced-motion .cb-anvil__hammer--right.is-slam { animation: none; }

@media (max-width: 900px) { .cb-anvil__hammer { display: none; } }


/* ═══════════════════════════════════════════════════════════════════════
   25 · PROOF-OF-CONCEPT BANNERS
   Bunnings red, because this is the one thing in the module that IS a
   warning — the single place the co-brand rule's "red is not a UI state"
   does not apply, since nothing here is a state the learner can be in.
   ═══════════════════════════════════════════════════════════════════════ */
.cb-pocbanner {
  display: block; background: var(--bn-red); color: var(--mo-white);
  border-radius: var(--radius-md);
  padding: clamp(16px, 2.4vw, 24px) clamp(18px, 2.6vw, 30px);
  margin-bottom: clamp(22px, 3vw, 34px);
  border-left: 8px solid var(--bn-red-deep);
}
.cb-pocbanner__text {
  display: block;
  font-family: var(--font-feature); text-transform: uppercase;
  font-size: calc(clamp(20px, 2.6vw, 32px) * var(--fs-scale));
  line-height: 1.06; letter-spacing: 0; color: var(--mo-white);
  text-wrap: balance;
}
/* On a dark screen the plain red loses its edge, so it gets a rule. */
.cb-pocbanner--onDark { border-left-color: var(--mo-white); }

/* The closing screen is the banner and nothing else. */
.cb-pocbanner--huge { margin: 0; padding: clamp(28px, 5vw, 60px) clamp(24px, 4vw, 56px); }
.cb-pocbanner--huge .cb-pocbanner__text { font-size: calc(clamp(30px, 6.4vw, 78px) * var(--fs-scale)); }

.cb-finale {
  display: flex; align-items: center; justify-content: center;
  min-height: calc(100vh - var(--header-h) - var(--footer-h) - 40px);
}
.cb-finale .cb-pocbanner { max-width: 1000px; width: 100%; }

/* Movember-only mode has no partner red to spend, so the banner goes black
   and keeps the red hairline it is entitled to as a warning. */
html[data-brand="mo"] .cb-pocbanner { background: var(--mo-black); border-left-color: var(--mo-white); }
