/* ==========================================================================
   Mobile layout overlay.

   Everything here is scoped to .mobile-device (real phone) or (pointer:coarse)
   (any touch device, including a phone asking for the desktop site — that
   request turns .mobile-device off, so capability queries are the only thing
   that still applies there).

   Desktop with a mouse matches neither and is untouched.
   ========================================================================== */

/* ---- 1. header: one row, links become icons ---------------------------- */
.mobile-device .header {
  padding: 6px 12px;
  gap: 8px;
  min-height: 0;
}
.mobile-device .header img {
  width: 34px; height: 34px;
  border-radius: 9px;
  flex: 0 0 auto;
}
/* name shrinks with an ellipsis before it ever pushes the icons off-screen */
.mobile-device .header > div:not(.links):not(.neural-bg) {
  min-width: 0;
  flex: 1 1 auto;
}
.mobile-device .header .name {
  font-size: 14px;
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* the affiliations line moves into About Me — it cost 2 wrapped lines here */
.mobile-device .header .sub { display: none; }

.mobile-device .header .links {
  margin-left: auto;
  flex: 0 0 auto;
  flex-wrap: nowrap;
  gap: 3px;
  font-size: 0;          /* kills the text nodes; icons carry the meaning */
}
.mobile-device .header .links a {
  width: 32px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 8px;
  color: var(--accent);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.mobile-device .header .links a:active { background: rgba(158,201,255,.16); }
.mobile-device .header .links a svg { width: 19px; height: 19px; display: block; }
/* the AI motif behind the header is decoration this screen cannot spare */
.mobile-device #headerNeural { display: none; }

/* the header slides away while you read and comes back the moment you scroll
   up, so the list gets the whole screen without losing the way back */
.mobile-device .header {
  position: sticky;
  top: 0;
  z-index: 60;
  transition: transform .22s ease;
  will-change: transform;
}
.mobile-device.m-hide-head .header { transform: translateY(-100%); }

/* ---- 2. map: 40vh, and nothing sits on top of it ------------------------ */
.mobile-device .app {
  min-height: 0;
}
/* main.css sets .app to calc(100vh - 77px) — a hard-coded header height that
   the mobile header has never actually been, so the difference showed as a
   band of body background along the bottom of the page. Let the column do the
   arithmetic instead: body owns the viewport, .app takes what the header
   leaves. dvh so the browser's own toolbar is excluded. */
.mobile-device body {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}
.mobile-device .app {
  flex: 1 1 auto;
  height: auto !important;
  min-height: 0;
}

/* Three stops on the chevron: 36vh, 22vh, closed. */
.mobile-device .left {
  height: 36vh !important;
  min-height: 190px !important;
}
/* two stops for the map/text trade, set by the bar between the panels.
   Full screen covers the "more map" end, so a third stop was noise. */
.mobile-device.m-text .left { height: 22vh !important; min-height: 150px !important; }

/* ---- the map/text split bar -------------------------------------------- */
.m-split {
  order: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 2px 0 3px;
  background: rgba(9, 16, 30, .55);
  border-top: 1px solid rgba(255,255,255,.06);
  border-bottom: 1px solid rgba(255,255,255,.06);
}
.m-split-b {
  display: flex; align-items: center; justify-content: center;
  width: 46px; height: 26px;
  background: none; border: 0; padding: 0;
  color: var(--accent);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.m-split-b svg { width: 17px; height: 17px; display: block; }
.m-split-b:disabled { opacity: .25; }
.m-split-grip {
  width: 34px; height: 3px; border-radius: 2px;
  background: rgba(158, 201, 255, .3);
}

/* The control bar rides along the bottom edge of the map, on the same line as
   the expand button, with no background of its own — the buttons carry their
   own translucency, so the scene reads straight through the row. As a solid
   band under the map this cost ~52px of a screen that has none to spare. */
/* One centred row along the bottom edge of the map: the play/speed controls
   and the full-screen button together, so nothing can be orphaned off the
   edge. Width follows the screen; if a narrow phone cannot fit the row it
   scrolls sideways rather than wrapping to a second line. */
.m-dock {
  position: absolute;
  left: 0;
  right: 0;
  bottom: max(8px, env(safe-area-inset-bottom, 0px));
  z-index: 28;
  display: flex;
  align-items: center;
  justify-content: center;         /* centred, whatever the screen width */
  flex-wrap: nowrap;
  gap: 5px;
  padding: 0 8px;
  background: none !important;     /* the row itself draws nothing */
  border: 0;
  box-shadow: none;
  backdrop-filter: none;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.m-dock::-webkit-scrollbar { display: none; }

/* inside the dock the control bar is a plain row, not a floating panel */
.mobile-device .m-dock .controls {
  position: static;
  transform: none;
  opacity: 1;
  pointer-events: all;
  background: none !important;
  border: none;
  box-shadow: none;
  padding: 0;
  gap: 4px;
  max-width: none;
  backdrop-filter: none;
  flex-wrap: nowrap;               /* never a second row */
  white-space: nowrap;
}
/* the inner groups app.js toggles are rows too */
.mobile-device .m-dock #standardControls,
.mobile-device .m-dock #roverControls {
  display: flex;
  flex-wrap: nowrap;
  gap: 4px;
}
/* each button carries the translucency instead of the bar behind them */
.mobile-device .m-dock .controls button {
  min-width: 38px;
  min-height: 34px;
  height: 34px;
  font-size: 12px;
  padding: 0 8px;
  flex: 0 0 auto;
  background: rgba(9, 16, 30, .34);
  border: 1px solid rgba(158, 201, 255, .20);
  color: #cfe2ff;
  backdrop-filter: blur(8px);
}
.mobile-device .m-dock #btnPause,
.mobile-device .m-dock #btnPause:hover { color: #ffffff; }
.mobile-device .m-dock .controls button.active {
  background: rgba(158, 201, 255, .20);
  border-color: rgba(158, 201, 255, .55);
  color: #ffffff;
}

/* On a narrow phone (iPhone SE and friends) eight buttons at full size
   overflow and the row scrolls instead of centring. Shave them a little so
   the whole toolbar fits and stays centred. */
@media (max-width: 370px) {
  .mobile-device .m-dock { gap: 4px; padding: 0 6px; }
  .mobile-device .m-dock .controls { gap: 4px; }
  .mobile-device .m-dock .controls button { min-width: 32px; padding: 0 5px; }
}

/* ---- 3. the buttons that were stacked in the same corner ---------------- */
/* Three things wanted the top corners of a 180px map:
     .obj-toggle          (hover-info.css:61)  top:12 right:12
     .instructions-toggle (main.css:855)       top:12 right:12   <- exact overlap
     .t3-replay           (tour3.css:144)      top:12 left:12
   On a phone the tour is replaced by a text sheet (.m-help), so tour3's own
   button and the tips button are both hidden here; desktop keeps them. */
.mobile-device .instructions-toggle,
.mobile-device .t3-replay { display: none !important; }

/* Object info drives a hover tag and there is no hover on a phone; the corner
   readout is a date and an "AU" figure with nothing to anchor them to.
   Keyed on .mobile-device alone, NOT on a class a script adds. This used to
   need .m-noinfo, which mobile.js - the last of 20 scripts - set at the end
   of startup, while hover-info.js creates the button eight scripts earlier.
   The result was the desktop Object info button sitting on the map through
   the whole load and then being swapped for the Full screen button, which
   reads as two different pages loading. .mobile-device is set by the inline
   script in <head>, so this hides it before the first paint. */
.mobile-device .obj-toggle,
.mobile-device .obj-corner { display: none !important; }

/* ---- 4. the floating map buttons --------------------------------------- */
.m-btn {
  position: absolute;
  z-index: 30;
  display: flex; align-items: center; justify-content: center;
  gap: 6px;
  min-width: 32px; height: 32px;
  padding: 0 8px;
  background: rgba(9, 16, 30, .55);
  border: 1px solid rgba(158, 201, 255, .26);
  border-radius: 10px;
  color: #cfe2ff;
  font: 600 11.5px/1 Inter, system-ui, sans-serif;
  backdrop-filter: blur(10px);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.m-btn svg { width: 17px; height: 17px; display: block; flex: 0 0 auto; }
.m-btn:active { background: rgba(158, 201, 255, .18); }
.m-help   { top: 8px; left: 8px; }
/* top-right, clear of the browser's bottom toolbar and of the object-info
   corner, which is hidden on mobile anyway */
.m-expand {
  top: max(8px, env(safe-area-inset-top, 0px));
  right: 8px;
  min-width: 38px; height: 32px;
  padding: 0 10px 0 8px;
  background: rgba(9, 16, 30, .78);
  border-color: rgba(158, 201, 255, .45);
}
/* The icon alone was not being found against a starfield. The word says what
   the control does and widens the target at the same time. */
.mobile-device .m-expand-t {
  font: 700 11px/1 Inter, system-ui, sans-serif;
  letter-spacing: .02em;
}
.mobile-device.m-full .m-expand {
  position: fixed;
  top: max(10px, env(safe-area-inset-top, 0px));
  right: 10px;
  z-index: 403;
}

.mobile-device.m-full .left {
  position: fixed;
  inset: 0;
  height: 100vh !important;
  height: 100dvh !important;       /* excludes the browser's own chrome */
  width: 100vw;
  z-index: 400;
  margin: 0;
}
/* Full screen: anchor the row to the VISUAL viewport. 100vh on a phone
   includes the strip behind the browser's own bottom toolbar, so an
   absolutely-positioned row inside a 100vh map sits underneath it — which is
   exactly how the full-screen exit button vanished. position:fixed measures
   against what is actually on screen. */
.mobile-device.m-full .m-dock {
  position: fixed;
  left: 0; right: 0;
  bottom: max(14px, env(safe-area-inset-bottom, 0px));
  z-index: 402;
}
.mobile-device.m-full body { overflow: hidden; }

/* ---- 4b. the "how to explore" card ------------------------------------- */
/* Sits over the top of the map, inside it, with no backdrop: the project list
   below stays readable and scrollable while it is up. */
.m-sheet {
  position: absolute; left: 8px; right: 8px; top: 46px; bottom: 8px;
  z-index: 35; display: none; align-items: flex-start;
  pointer-events: none;
}
.mobile-device.m-sheet-on .m-sheet { display: flex; }
.m-sheet-card {
  position: relative;
  width: 100%;
  max-height: 100%;
  overflow-y: auto;
  pointer-events: auto;
  background: rgba(12, 23, 40, .94);
  border: 1px solid rgba(158, 201, 255, .4);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
  padding: 12px 14px;
  color: var(--ink);
}
.m-sheet-h { font: 700 15px/1.2 Inter, system-ui, sans-serif; margin-bottom: 4px; }
.m-sheet-sec {
  font: 600 9.5px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent); margin: 14px 0 6px;
}
.m-sheet-card ul { margin: 0; padding-left: 18px; }
.m-sheet-card li { font-size: 12.5px; line-height: 1.4; margin-bottom: 3px; }
.m-sheet-x.m-sheet-close {
  position: absolute; top: 4px; right: 4px; margin: 0;
  width: 36px; min-height: 36px; padding: 0;
  font-size: 20px; background: none; border: 0;
}
/* first visit: the button blinks three times before the card opens from it */
.m-help.m-blink { animation: m-blink .6s ease-in-out 3; }
@keyframes m-blink {
  50% { background: rgba(255, 210, 127, .35); border-color: #ffd27f; color: #fff; }
}
@media (prefers-reduced-motion: reduce) { .m-help.m-blink { animation: none; } }
.m-sheet-card b { color: #cfe2ff; }
.m-sheet-x {
  margin-top: 8px; width: 100%; min-height: 38px;
  background: rgba(158, 201, 255, .16);
  border: 1px solid rgba(158, 201, 255, .45);
  border-radius: 10px; color: #cfe2ff;
  font: 600 13px/1 Inter, system-ui, sans-serif;
}

/* ---- 5. publication list: figure + institution + title ------------------ */
.mobile-device .pub-desc,
.mobile-device .pub-meta,
.mobile-device .pub-links { display: none; }
.mobile-device .pub-card { padding: 10px; margin-bottom: 8px; }
/* main.css:36-47 sets every list/detail size as
   `calc(Npx * var(--list-font-scale)) !important`, so a plain font-size here
   is silently ignored. Same form, mobile base values, higher specificity —
   this keeps the visitor's own text-size buttons working. */
.mobile-device .pub-card  { font-size: calc(13px   * var(--list-font-scale)) !important; }
.mobile-device .pub-title { font-size: calc(14px   * var(--list-font-scale)) !important;
                            line-height: 1.3; }
.mobile-device .pub-subinst { font-size: calc(10.5px * var(--list-font-scale)) !important;
                            opacity: .78; line-height: 1.35; margin-top: 3px; }
/* the grouped band above each card already names the institution — printing
   it again inside the card cost ~30px per card for a repeated string */
.mobile-device .pub-card .pub-inst { display: none; }

/* A thumbnail beside the text, not a full-width figure above it. Full width
   was tried and rejected: it turns the list into a gallery and pushes the
   titles apart, and this is a list you read.

   float:left is set explicitly because main.css:464 drops the float under
   800px, so on a phone the image has always been a block ABOVE the text -
   the text has never sat beside it here. 124x86 is ~20% wider than the old
   104x72 and 43% more area, which is as far as it goes before the title
   column gets too narrow to read.

   object-fit:contain, never cover: these are scientific figures and cropping
   one is not acceptable. */
.mobile-device .pub-image {
  float: left;
  width: 124px;
  max-width: 38%;
  height: 86px !important;
  min-height: 0 !important;
  aspect-ratio: auto;
  margin: 0 12px 6px 0;
}
.mobile-device .pub-image img {
  width: 100%;
  height: 100% !important;
  object-fit: contain !important;
}

/* the list's own title row wrapped to two lines next to SET TEXT SIZE */
.mobile-device .right > .section-title {
  padding: 8px 12px;
  font-size: 11px;
  gap: 8px;
}
.mobile-device .right > .section-title .text-size-label { font-size: 9px; }
.mobile-device .right > .section-title button { width: 26px; height: 26px; }

/* ---- 6. detail view: the header bar was desktop-sized ------------------- */
.mobile-device .detail-header {
  padding: 10px 12px;
  gap: 8px;
}
.mobile-device .detail-header h2 {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .02em;
  opacity: .75;
  margin: 0;
}
.mobile-device .detail-header .text-size-controls { gap: 6px; }
.mobile-device .detail-header .text-size-controls button { width: 26px; height: 26px; }
.mobile-device .detail-header .text-size-label { font-size: 9px; }
.mobile-device .detail-content { padding: 12px; }
/* same !important/scale form as the list above — this is the "publication
   details is written way too big" complaint: the base was 24px for the title
   and 16px for the body, sized for a 500px desktop column. */
.mobile-device .detail-title {
  font-size: calc(17px * var(--list-font-scale)) !important;
  margin-bottom: 8px; line-height: 1.25;
}
.mobile-device .detail-inst { font-size: calc(12px * var(--list-font-scale)) !important;
                              margin-bottom: 8px; }
.mobile-device .detail-subinst { font-size: calc(11px * var(--list-font-scale)) !important; }
.mobile-device .detail-desc,
.mobile-device .detail-extended-desc {
  font-size: calc(13.5px * var(--list-font-scale)) !important;
  line-height: 1.55;
}
.mobile-device .detail-extended { padding: 0 12px 16px; }
.mobile-device .detail-image { max-width: 100%; margin-bottom: 12px; }

/* ---- VIPER on a phone: no mission furniture ----------------------------
   The HUD panel (samples, speed, distance) and the EXIT MISSION button are
   desktop affordances. On a 390px screen they cover the drive view, and the
   way out is already the map's own controls. Desktop keeps both. */
.mobile-device #missionHud,
.mobile-device #missionExit { display: none !important; }

/* the canvas owns every gesture on it: one finger rotates/pans, two pinch.
   main.css allowed pan-x pan-y, which let the browser scroll the page out
   from under a two-finger pinch. The list below is still scrollable. */
.mobile-device #canvas3d,
.mobile-device #moonSurface { touch-action: none; }

/* ---- 7. touch capability, independent of the user-agent ----------------- */
/* A phone set to "Desktop site" loses .mobile-device entirely. It still gets
   these, so the divider is grabbable and the hit targets are finger-sized. */
@media (pointer: coarse) {
  .resizer {
    width: 14px;
    touch-action: none;          /* required, or the browser scrolls instead */
    background: rgba(158, 201, 255, .10);
  }
  .resizer::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 3px; height: 40px;
    border-radius: 2px;
    background: rgba(158, 201, 255, .5);
  }
  /* A phone on "Desktop site" lays out at ~980px and scales that onto a
     ~393px screen, so the 14px strip above lands as 5.6 PHYSICAL pixels -
     the reason the divider is almost impossible to catch with a thumb. The
     answer is a bigger target, not a fatter line: stretch the ::before box
     15px past each edge so the grab area is ~44px to a finger, while what
     you SEE stays the 14px strip. Pointer events on it bubble to .resizer,
     which owns the drag.
     Note what is deliberately NOT declared here: `content`. main.css:194
     puts the visible grip glyph in this same pseudo-element, and redeclaring
     content would erase it on every coarse-pointer device. Only the box is
     touched, and the flex centring puts the glyph back where the auto
     position had it, so nothing looks different. */
  .resizer::before {
    top: 0; bottom: 0;
    left: -15px; right: -15px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .controls button { min-height: 34px; }
}

/* ---- 12. bigger toolbar in full screen ---------------------------------- */
/* The dock buttons are 34px because a 40vh map has no vertical room to spare.
   Full screen does have the room, and the rover's arrows are the one control
   you HOLD DOWN rather than tap, so they get the largest target of all.
   Height is what makes a target hittable, so on a narrow phone the widths are
   shaved back rather than the heights. */
.mobile-device.m-full .m-dock,
.mobile-device.m-full .m-dock .controls { gap: 7px; }

.mobile-device.m-full .m-dock .controls button {
  min-width: 44px;
  min-height: 44px;
  height: 44px;
  font-size: 14px;
  padding: 0 10px;
}
.mobile-device.m-full .m-dock #roverControls button {
  min-width: 54px;
  min-height: 48px;
  height: 48px;
  font-size: 21px;
  line-height: 1;
}
.mobile-device.m-full .m-expand { min-width: 44px; height: 44px; }

@media (max-width: 370px) {
  .mobile-device.m-full .m-dock,
  .mobile-device.m-full .m-dock .controls { gap: 5px; }
  .mobile-device.m-full .m-dock .controls button { min-width: 38px; padding: 0 7px; }
  .mobile-device.m-full .m-dock #roverControls button { min-width: 46px; }
}

/* ---- 13. the closed stop ------------------------------------------------ */
/* The third chevron stop. The map goes, the chevron STAYS — it is the only way
   to bring the map back, so hiding it here would strand the visitor in a list
   with no route to the solar system. */
.mobile-device.m-read .left { display: none !important; }

/* The two titles replace the static "Publications & Projects" text, so the
   mode switch costs no vertical height on a screen that has none to spare. */
/* ---- 15. ?fig=wide — the full-width card, for comparison ---------------- */
/* Temporary A/B so the two card layouts can be judged on a real phone.
   Delete this block and the m-fig-wide line in mobile.js once decided. */
.mobile-device.m-fig-wide .pub-image {
  float: none;
  width: 100%;
  max-width: 100%;
  height: auto !important;
  aspect-ratio: 16 / 9;
  margin: 0 0 10px;
}

/* ---- 16. landscape: the three stops trade WIDTH, not height ------------ */
/* css/main.css:1373 already turns .app into a row in landscape and gives the
   map 42% of the width. Section 2 of THIS file then forces
   height: 36vh !important; min-height: 190px !important on .left - written
   for the stacked portrait layout, and it wins on load order because this
   file comes last. Measured at 844x390 before this block existed:
     .left     354x190 inside a 337px-tall row  -> 147px of dead sky under it
     .m-split  844x397 at 0,0                   -> the chevron over the screen
     .resizer  order:0                          -> the divider left of the map
   All three are corrected here rather than in main.css, so the portrait
   layout and the desktop layout are both left exactly as they are.
   .m-full is excluded throughout: full screen is position:fixed inset:0 and
   must keep its own 100vw/100vh box. */
@media (orientation: landscape) {
  .mobile-device:not(.m-full) .left,
  .mobile-device:not(.m-full).m-text .left {
    height: 100% !important;
    min-height: 0 !important;
  }

  /* the stops trade horizontal space now. m-read keeps the display:none from
     section 13, which is what closes the map entirely. */
  .mobile-device:not(.m-full) .left {
    flex: 0 0 42% !important;
    width: 42% !important;
  }
  .mobile-device:not(.m-full).m-text .left {
    flex: 0 0 27% !important;
    width: 27% !important;
  }

  /* the chevron becomes the vertical divider between the two panels */
  .mobile-device:not(.m-full) .m-split {
    flex: 0 0 auto;
    flex-direction: column;
    gap: 16px;
    padding: 0 4px;
    border-top: 0;
    border-bottom: 0;
    border-left: 1px solid rgba(255,255,255,.06);
    border-right: 1px solid rgba(255,255,255,.06);
  }
  /* 46x26 laid on its side. The arrows still point where the map EDGE moves:
     rotating -90deg turns the portrait "up = shrink" into "left = shrink",
     which is the same promise in the new axis. */
  .mobile-device:not(.m-full) .m-split-b { width: 28px; height: 46px; }
  .mobile-device:not(.m-full) .m-split-b svg { transform: rotate(-90deg); }
  .mobile-device:not(.m-full) .m-split-grip { width: 3px; height: 34px; }

  /* main.css's landscape block shows .resizer as a 2px line but never gives
     it an order, so it defaults to 0 and renders BEFORE the map. The chevron
     is the divider in this layout; the line is redundant either way. */
  .mobile-device .resizer { display: none !important; }
}

/* the Classic Portfolio pill is an icon here like every other header link */
.mobile-device .header .links a.portfolio-cta {
  padding: 0;
  border: 0;
  border-radius: 8px;
  font-weight: 400;
}
