/* ═══════════════════════════════════════════════════════════════════════
   MOBILE — behaviour the demo never had.

   The prototype is desktop-first and its mobile rules are thin: roughly one
   `max-width:1000px` block per section saying "stack it". The verbatim port
   inherited that faithfully, so what follows is design work, not port repair.

   Every selector is prefixed with its .mf-*-mount root. That is not
   decoration: it is one extra class of specificity, so these rules outweigh
   the demo's own `.sec-flow .x` (0,2,0) without reaching for !important, and
   they keep working wherever in the cascade this file ends up. It was written
   to survive loading BEFORE the demo's stylesheets, which is where it had to
   live while home-v2's page custom-code block was returning 406 to every
   write. Verified in that position; loading it after only makes it safer.
   ═══════════════════════════════════════════════════════════════════════ */


/* ── Slack: one cause, the whole overflow list ──────────────────────────
   At 402px the section clipped eleven distinct elements — the rig at +159px,
   the clip deck at +198px, its next button at +206px. They are not eleven
   bugs.

   `.flow` is a fixed 560x520 coordinate space (every bubble, agent and pill
   inside it is absolutely positioned in that space) and the demo only ever
   scales it VISUALLY. A transform does not change layout size, so `.flow`
   goes on claiming 560px. The stacked grid column is `1fr`, which is
   `minmax(auto,1fr)`, and that `auto` floor is the item's min-content — 560.
   So the single column grows to 560 inside a 322px container, and the clip
   deck, being `width:100%` of that column, is dragged off-screen with it.

   Capping the floor at zero fixes the entire right-hand column. The rig then
   has to be made to genuinely fit, below. */
@media (max-width: 1000px){
  .mf-slack-mount .sec-flow .cols{ grid-template-columns: minmax(0, 1fr); }
  .mf-slack-mount .sec-flow .cols > *{ min-width: 0; }
}

/* The rig scales in steps rather than fluidly because CSS cannot divide two
   lengths to produce the unitless number `scale()` wants. Each step is sized
   for the NARROWEST viewport that matches it, so the rig never overhangs
   inside a band. */
@media (max-width: 640px){
  .mf-slack-mount .sec-flow .mf{ padding: 88px 20px; }
  .mf-slack-mount .sec-flow .flow{
    /* Scale about the TOP CENTRE, then hand back the layout space the
       transform freed — symmetrically, half off each side. Without the
       negative margins the row goes on reserving the full unscaled 560x520
       box and the grid fix above is undone; splitting them evenly is what
       keeps the rig centred instead of hugging one edge. */
    width: 560px;
    height: 520px;                 /* the demo's mobile block sets 412 */
    transform: scale(var(--mf-rig));
    transform-origin: top center;
    margin: 0 calc(560px * (var(--mf-rig) - 1) / 2)
              calc(520px * (var(--mf-rig) - 1)) ;
  }
  /* The two pills carry the section's actual message and are 11.5px at full
     size, which the scale turns into 7px. Counter-sizing puts them back where
     the demo drew them. The hub's 8.5px label is deliberately NOT counter-
     sized: its circle is 64px, and text large enough to read would not fit
     inside it. */
  .mf-slack-mount .sec-flow .flow .pill{ font-size: calc(11.5px / var(--mf-rig)); }

  /* Centred on a phone. The demo's head is a 640px left-aligned column
     against a wide layout; at 402px that reads as text stranded on one side
     of an otherwise centred section. Headings and lede centre, and the two
     columns stack centred under them.
     Card BODY copy is deliberately left untouched below — centring a
     five-line paragraph costs more readability than the symmetry buys. */
  .mf-slack-mount .sec-flow .head{ max-width: none; margin: 0 auto 40px; text-align: center; }
  .mf-slack-mount .sec-flow .head h2{ font-size: 28px; }
  .mf-slack-mount .sec-flow .head p{ font-size: 16px; }
  .mf-slack-mount .sec-flow .cols{ justify-items: center; gap: 40px; }
  .mf-slack-mount .sec-flow .slack{ width: 100%; }
  .mf-slack-mount .sec-flow .meta{ justify-content: center; }

  /* The clip panel reserves 92px on its right for the next button, which on a
     wide layout is the deck's own margin. At 402px that reads as a narrow
     card shoved against the left edge with a button floating in empty space.
     Centre it and let the button sit ON the card's edge, the way a carousel
     control normally does. left/right/margin rather than a transform —
     the deck script animates `transform` on these panels. */
  .mf-slack-mount .sec-flow .pnl{
    left: 0; right: 0; margin: 0 auto; width: calc(100% - 52px);
  }
  .mf-slack-mount .sec-flow .deck-next{ right: 0; }
}

.mf-slack-mount .sec-flow{ --mf-rig: 1; }
@media (max-width: 640px){ .mf-slack-mount .sec-flow{ --mf-rig: .90; } }
@media (max-width: 560px){ .mf-slack-mount .sec-flow{ --mf-rig: .77; } }
@media (max-width: 480px){ .mf-slack-mount .sec-flow{ --mf-rig: .63; } }
@media (max-width: 400px){ .mf-slack-mount .sec-flow{ --mf-rig: .56; } }
@media (max-width: 360px){ .mf-slack-mount .sec-flow{ --mf-rig: .49; } }


/* ── Case studies: the deck stops pretending to have depth ──────────────
   On desktop the eleven slots fan out — the second sits 296px right of the
   front, the third 486px — and the depth reads. The demo's stacked mode parks
   them 22px and 44px apart, which at 402px is not depth, it is three cards
   printed on top of each other: the second card's label ("Vulnerability and
   Exposure Backlog") paints straight across the front card's, and the back
   cards' right edges stick out past the front one.

   So on a phone the deck becomes what it already has the controls for — one
   card, eleven dots and two arrows. `!important` is unavoidable here and only
   here: fleet.js writes `opacity` as an inline style on every slot, and an
   inline style outranks any selector without it. */
@media (max-width: 640px){
  .mf-fleet-mount .sec-cs .slot:not(.front){ opacity: 0 !important; }
  .mf-fleet-mount .sec-cs .slot:not(.front) .label{ opacity: 0; }

  /* Centre the section and the deck. The head is a left-aligned column in the
     demo and the stage is a left-aligned flex column; on a phone both strand
     their content against the left edge of a section that is otherwise
     symmetrical. The card's own paragraphs stay left-aligned. */
  .mf-fleet-mount .sec-cs .head{ max-width: none; text-align: center; }
  .mf-fleet-mount .sec-cs .head h2{ font-size: 28px; }
  .mf-fleet-mount .sec-cs .stage{ align-items: center; }
  .mf-fleet-mount .sec-cs .ship{ align-self: center; }
  /* The slots are absolutely positioned at left:0 and capped at 420px, so on
     any phone wider than 420 they hug the left edge of a centred deck.
     Centred with a margin rather than translateX(-50%) because fleet.js owns
     `transform` on every slot — it writes translate3d/rotateY there — and a
     transform here would be overwritten on the next paint. The percentage in
     margin-left resolves against the deck, so this tracks the cap. */
  .mf-fleet-mount .sec-cs .slot{ left: 50%; margin-left: calc(min(100%, 420px) / -2); }
  .mf-fleet-mount .sec-cs .ctl{ justify-content: center; }
  .mf-fleet-mount .sec-cs .arw{
    background: #fff; border-color: #fff; color: #0FBE68;
  }
  .mf-fleet-mount .sec-cs .arw:hover{
    background: #fff; border-color: #fff; color: #0FBE68;
  }

  /* The eleven dashes do not fit across a phone and read as a squashed
     ladder. Collapse them to ONE bar: every dash but the active one is
     hidden, and the active one stretches to fill the row. The demo already
     animates `i.on b` from 0 to full width on the autoplay timer, so what is
     left is a single progress bar showing how long this card has been up —
     which is the indicator, not a decoration. */
  /* A bar the full width of the row read as a rule under the card rather
     than a progress indicator. Short and centred, it reads as a timer. */
  .mf-fleet-mount .sec-cs .dots{ flex: 0 0 104px; }
  .mf-fleet-mount .sec-cs .dots i{ display: none; }
  .mf-fleet-mount .sec-cs .dots i.on{ display: block; width: 100%; }

  /* The flying probe lands ON the card: measured at 402px it occupies
     y1510-1632 while the front card runs y1437-1767. The section's own
     #cs-ship is innocent — it sits at y1192, clear above the deck — so this
     targets the journey layer and only the journey layer.

     Two things decide the selector. The layer is appended to <body>, NOT
     inside .mf-fleet-mount, so a mount-scoped rule would match nothing; and
     the attribute is carried along purely to outweigh ship.css's own
     `.ship-journey`, which loads after this file.

     opacity, NEVER display:none — fleet.js's ignite() defers to
     `[data-ship-journey]` when one is present and waits for its touchdown to
     fire `beam-on`, and that touchdown is computed from measured rects. Take
     the element out of layout and the beam never fires, so the cards never
     reveal at all and the deck photographs empty.

     REVISED: hiding it was the wrong answer — it is the spaceship, and losing
     it was immediately noticed. It stays visible and is scaled down instead,
     so it reads as a probe arriving rather than a full-size craft parked on
     the paragraph. Its transform belongs to ship.js, so the size comes from
     width/height on the image, which the script does not touch. */
  .ship-journey[data-ship-journey]{ pointer-events: none; }
  .ship-journey img{ width: 84px; height: auto; }
}


/* ── Hero: the luminance twin is a desktop trick, and mobile breaks it ──
   `.hero-onplanet` duplicates the headline clipped to the planet by a
   luminance mask, so the copy repaints DARK where it crosses the bright limb.
   That works while the planet is a disc occupying part of the hero.

   At 402px the planet is 846x1440 against a 402x900 viewport — it IS the
   background. So the trick fires across the whole headline and paints dark
   text onto mid-grey cloud, which is the unreadable header and lede. Turning
   the twin off restores plain white copy; darkening the planet gives that
   copy something to sit on. */
/* 767 not 640 (audit 2026-07-31): at 641-767 the planet still fills most of
   the viewport, so the twin painted its ghost over the headline in the one
   band neither this file (640) nor the tablet overlay (768+) policed. The
   phone design's boundary is 767; this block now agrees. */
@media (max-width: 767px){
  /* !important because mf.js writes `display` INLINE on the twin as it drives
     it, and an inline style outranks any selector without it. Measured: the
     plain rule left it computing `display: block`. */
  .hero .hero-onplanet[data-mask-twin]{ display: none !important; }

  /* Two problems, one rule. brightness gives the white copy its contrast
     back; the mask stops the planet at the hero's own bottom edge.

     It bottoms out at y1314 while the hero ends at 900, so 414px of it hangs
     over the case-study section and its bright limb swallows that section's
     white headline. The stops are computed from the image's own box, not
     guessed: it spans y-126 to y1314, so the hero's bottom edge falls at 71%
     of its height. Fading 58% -> 74% lands the fade on that edge.

     A gradient mask was rejected here once, for banding — but that was the
     old plate, where image and page differed by 7 levels of red and a smooth
     ramp quantised into ~48px steps. This fades the planet's own body, across
     460px, at half brightness. Different problem, and the alternative is
     `overflow:hidden` on the hero, which slices the limb on a hard line. */
  .hero img.hero-planet{
    filter: brightness(.30);
    -webkit-mask-image: linear-gradient(to bottom, #000 58%, transparent 74%);
            mask-image: linear-gradient(to bottom, #000 58%, transparent 74%);
  }

  /* NO SCRIM, deliberately -- the second time this page has taught the same
     lesson. A radial one showed its box edge; replacing it with a full-bleed
     vertical ramp still drew a straight line across the planet at the same
     place, because a long smooth gradient over a near-flat dark image
     quantises: consecutive 8-bit values cover tens of pixels each and the
     step reads as a hard edge. It is the identical failure that got a
     gradient mask rejected on the planet plate earlier.

     A filter is a uniform multiply, so it has no ramp and nothing to band.
     Contrast for the copy comes from that alone. */
  .hero .hero-lede{ color: rgba(238,243,228,.94); }
}


/* ── Slack clip deck: one card, control underneath ─────────────────────
   Same treatment as the case-study deck, for the same reason: a side-mounted
   next button costs 92px of a 402px card and leaves the control floating in
   dead space beside it. Below the card, the card gets the full width. */
@media (max-width: 640px){
  .mf-slack-mount .sec-flow .pnl{ width: 100%; }
  .mf-slack-mount .sec-flow .deck{ margin-bottom: 68px; }
  .mf-slack-mount .sec-flow .deck-next{
    top: auto; bottom: -62px; right: auto; left: 50%;
    transform: translateX(-50%);
  }
  /* the demo's hover/active rules re-assert translateY(-50%), which would
     throw the button back up now that it is centred horizontally instead */
  .mf-slack-mount .sec-flow .deck-next:hover{ transform: translateX(-50%) scale(1.09); }
  .mf-slack-mount .sec-flow .deck-next:active{ transform: translateX(-50%) scale(.95); }
}


/* ── Round 2, Tudor 2026-07-29 ─────────────────────────────────────────── */

@media (max-width: 640px){

  /* The rig's hub is a 64px dashed circle carrying "Moonfort Agents" at
     8.5px. Scaled to fit a phone that is ~5px of type inside a ~40px ring —
     unreadable, and it crowds the six agents orbiting it. Replace both the
     dashed orbit and the hub with a legible pill beneath the crew.

     opacity, not display:none, on the hub: the flow timeline slides each
     agent IN from the hub's position and measures it to do so. Take it out of
     layout and the arrivals compute from a zero rect. The orbit circle is
     pure decoration and can go properly. */
  .mf-slack-mount .sec-flow .rig .orbit{ display: none; }
  /* !important because the flow timeline animates the hub's opacity with
     anime.js, which writes it INLINE. Measured: the plain rule left the
     dashed circle and its 5px label still painting. */
  .mf-slack-mount .sec-flow .flow .hub{ opacity: 0 !important; }
  .mf-slack-mount .sec-flow .flow::after{
    content: 'Moonfort agents';
    /* rig space: the orbit is r=78 about (280,360) and an agent is 44px, so
       the lowest agent's bottom edge is 360+78+22 = 460. 474 clears it. */
    position: absolute; left: 280px; top: 474px; translate: -50% 0;
    padding: 7px 14px; border-radius: 100px; white-space: nowrap;
    background: var(--bg); border: 1px solid var(--hair);
    font-family: var(--mono); letter-spacing: .03em; color: var(--body);
    /* counter-scaled like the two arc pills, so it reads at its drawn size
       rather than at 7px */
    font-size: calc(11.5px / var(--mf-rig));
  }

  /* Controls, in the order asked for: card, then the three tabs, then the
     clip label, then the two arrows centred under it. .deck-ctl is appended
     after .meta by the module; the deck's own edge-mounted arrow steps aside
     for it here and stays the desktop control. */
  .mf-slack-mount .sec-flow .deck-next{ display: none; }
  .mf-slack-mount .sec-flow .deck{ margin-bottom: 0; }
  /* The panel is full width here, so the two cards parked behind it -- which
     the deck offsets to the RIGHT -- stick out past its edge instead of
     hiding under it. Their opacity is written inline by paint(), so it
     cannot be overridden without also hiding the front card; clip the deck
     instead. Costs the card's outer drop shadow, which is barely visible on
     this background. */
  .mf-slack-mount .sec-flow .deck{ overflow: hidden; }
  .mf-slack-mount .sec-flow .meta{ flex-direction: column; gap: 12px; margin-top: 24px; }
  .mf-slack-mount .sec-flow .deck-ctl{
    display: flex; justify-content: center; gap: 18px; margin-top: 18px;
  }
  /* White plate, green glyph -- the site's own button treatment, and the
     same on both decks so the two carousels read as one control language.
     `color` rather than a fill: both arrow sets stroke with currentColor. */
  .mf-slack-mount .sec-flow .deck-arw{
    width: 46px; height: 46px; border-radius: 50%;
    display: grid; place-items: center; cursor: pointer;
    background: #fff; border: none; color: #0FBE68;
    box-shadow: 0 10px 24px -12px rgba(0,0,0,.5), 0 0 18px 3px rgba(122,255,155,.22);
    transition: transform .28s var(--spring);
  }
  .mf-slack-mount .sec-flow .deck-arw:active{ transform: scale(.94); }
  .mf-slack-mount .sec-flow .deck-arw svg{ width: 21px; height: 21px; display: block; }

  /* Case study: the label above the card is the only thing still hanging off
     the left edge of an otherwise centred section. */
  .mf-fleet-mount .sec-cs .label{ text-align: center; max-width: none; }

  /* Ship off the phone entirely, both of them: the section's own probe and
     the flying journey layer. The journey keeps its geometry (opacity, never
     display:none) because ignite() waits on its touchdown to fire `beam-on`,
     and a layer with no rect never touches down, so the cards would never
     reveal. The section's own #cs-ship has no such contract on a phone — the
     beam and haze it feeds are already display:none here — so it can go. */
  .mf-fleet-mount .sec-cs .ship{ display: none; }
  .ship-journey[data-ship-journey]{ opacity: 0; }
}



/* ── Footer, phone arrangement ─────────────────────────────────────────
   The demo's footer is a two-up: brand on the left, three link columns
   pushed to the right by `justify-content: space-between`. At 402px that
   wraps into a ragged left-aligned pile with a 60px gutter still in it.
   Stack it centred, and let the three columns sit as a row of three since
   they are short enough to. */
@media (max-width: 640px){
  .mf-foot-mount .pg-foot{ padding: 72px 24px 56px; min-height: 0; }
  .mf-foot-mount .pg-foot__grid{
    flex-direction: column; align-items: center; text-align: center; gap: 40px;
  }
  .mf-foot-mount .pg-foot__brand{ max-width: 300px; }
  .mf-foot-mount .pg-foot__word{ font-size: 26px; margin-bottom: 10px; }
  .mf-foot-mount .pg-foot__tag{ margin-bottom: 8px; }
  .mf-foot-mount .pg-foot__cols{
    gap: 30px; justify-content: center; flex-wrap: wrap; width: 100%;
  }
  .mf-foot-mount .pg-foot__cols > div{ min-width: 92px; }
  .mf-foot-mount .pg-foot__cols .pg-eyebrow{ margin-bottom: 10px; }
  .mf-foot-mount .pg-foot__cols a{ padding: 4px 0; }
}
