/* ────────────────────────────────────────────────────────────────
   Sentrint — mobile navigation sheet (partials/_mobile_nav.html)

   Its own file rather than a block inside app.css, because the two
   surfaces that need it most do NOT load app.css: index.html and
   pricing.html inline their own palette, and the wiki keeps its own
   head. One cached file serves all four consumers instead of ~145
   lines re-parsed on every document.

   Linked from:
     partials/_tokens.html    (every signed-in app page)
     partials/_wiki_head.html (the wiki)
     index.html, pricing.html (marketing)

   The ONLY rules still inline in the partial are the two that depend
   on the caller's breakpoint (mnav_at: 900 in the app topbar, 780 on
   marketing and the wiki) — a static file cannot carry a Jinja value.

   Tokens: the app and the marketing pages ship different names for the
   same palette (--accent vs --brass, --border vs --line). The aliases
   below resolve to whichever exists, so this file works under both
   without either side changing.
   ──────────────────────────────────────────────────────────────── */

  .mnav-trigger, .mnav {
    --mn-accent: var(--accent, var(--brass));
    --mn-ink: var(--ink);
    --mn-faint: var(--ink-4, var(--faint));
    --mn-line: var(--border, var(--line));
    --mn-on-accent: var(--cream, #0b1424);
  }

  /* ── Trigger + close ──────────────────────────────────────────────────────
     44px square: Apple's touch-target floor. These two are the same control in
     two states — one opens the sheet, one closes it — so they share a body and
     differ only in colour and in whether they are visible at this width. */
  .mnav-trigger, .mnav-close {
    width: 44px; height: 44px; margin-right: -10px;
    display: inline-flex; align-items: center; justify-content: center; flex: none;
    background: none; border: 0; padding: 0; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .mnav-trigger:focus-visible, .mnav-close:focus-visible {
    outline: 2px solid var(--mn-accent); outline-offset: 2px; border-radius: 8px;
  }
  /* Hidden above the breakpoint; the partial's own media query reveals it. */
  .mnav-trigger { display: none; color: var(--mn-ink); }
  .mnav-close { color: var(--mn-accent); }
  .mnav-close svg { width: 19px; height: 19px; stroke: currentColor; stroke-width: 1.6;
    fill: none; stroke-linecap: round; }

  /* ── Bars ─────────────────────────────────────────────────────────────────
     Three, with the middle one short — the shape the founder picked. The pill
     cap is the one detail taken from that reference literally; the weight is
     not. The reference is drawn thick, and this product is drawn in hairlines:
     a chunky icon would be the heaviest line on the page it sits at the top of.
     So 1.5px, the same rule weight as every border in the system.

     19x14 box, bars on an integer 6px pitch. Both numbers are load-bearing.
     The box height must be EVEN, because the span is centred in a 44px button:
     an odd height puts the whole stack on a half pixel, and at 1.5px tall the
     three bars then round to different numbers of device rows. That is not
     hypothetical — a 13px box shipped here first and drew 1 row / 2 rows / 2
     rows at 1dppx, so the top bar read visibly lighter than the other two.
     Tops of 0/6/12 in an even box measure even at 1x, 2x and 3x. Re-measure at
     all three if you change the height or the pitch. */
  .mnav-bars { position: relative; display: block; width: 19px; height: 14px; }
  .mnav-bars i { position: absolute; left: 0; top: 0; width: 19px; height: 1.5px;
    border-radius: 999px; background: currentColor;
    transition: transform .3s cubic-bezier(.22,1,.36,1), opacity .2s ease; }
  /* Only the short bar scales, so only it pivots from the left — the outer two
     keep the default centre origin, which is what makes them cross cleanly. */
  .mnav-bars i:nth-child(2) { top: 6px; transform-origin: left center; transform: scaleX(.55); }
  .mnav-bars i:nth-child(3) { top: 12px; }

  /* The short bar rules out to full width on approach, the way every other line
     in this product gets drawn. It is the only idle movement in the trigger.
     scaleX keeps it off the layout path, and (hover: hover) keeps a tap from
     leaving it stuck extended on a phone — which is where this trigger lives.
     Both rules are pinned to the closed state: they outrank the open state on
     specificity, so without that guard, mousing over the trigger to close the
     sheet would pull the vanished bar back out mid-gesture. */
  @media (hover: hover) {
    .mnav-trigger[aria-expanded="false"]:hover .mnav-bars i:nth-child(2) { transform: scaleX(1); }
  }
  .mnav-trigger[aria-expanded="false"]:focus-visible .mnav-bars i:nth-child(2) { transform: scaleX(1); }

  /* Open: the outer two converge on the centre line and cross, and the short one
     retracts into the left edge it grew from. The same three elements throughout,
     so open and close are one continuous gesture rather than a swap. */
  [aria-expanded="true"] .mnav-bars i:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  [aria-expanded="true"] .mnav-bars i:nth-child(2) { transform: scaleX(0); opacity: 0; }
  [aria-expanded="true"] .mnav-bars i:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
  [aria-expanded="true"] .mnav-bars { color: var(--mn-accent); }
  .mnav-trigger[aria-expanded="true"] { color: var(--mn-accent); }

  /* ── Sheet ────────────────────────────────────────────────────────────────
     Frosted rather than solid. The blur is doing real work: it holds the page
     you were on in view, faintly, so the menu reads as a layer over your place
     rather than a new destination. */
  .mnav { position: fixed; inset: 0; z-index: 900; display: flex; flex-direction: column;
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    -webkit-backdrop-filter: blur(34px) saturate(150%);
    backdrop-filter: blur(34px) saturate(150%);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .26s ease, visibility .26s; }
  .mnav[data-open="true"] { opacity: 1; visibility: visible; pointer-events: auto; }
  /* Safari and Firefox without color-mix still need a floor, or the sheet is
     transparent and the text lands on the page underneath. It reads the page's
     own --bg rather than a midnight literal: a hardcoded dark slab would put
     near-black text on near-black in light mode, which is the exact bug this
     fallback exists to prevent. Opaque, so the blur simply does nothing. */
  @supports not (background: color-mix(in srgb, red 50%, transparent)) {
    .mnav { background: var(--bg); }
  }

  .mnav-top { display: flex; align-items: center; justify-content: flex-end;
    height: 78px; padding: 0 22px; flex: none; border-bottom: 1px solid var(--mn-line); }

  .mnav-body { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
    padding: 8px 22px 0; }

  /* Identity row (signed-in only). Name in Spectral, plan as a quiet mono line —
     the same pairing the profile dropdown uses on desktop. */
  .mnav-id { display: flex; align-items: center; gap: 13px; padding: 20px 0 22px;
    border-bottom: 1px solid var(--mn-line); }
  .mnav-av { width: 40px; height: 40px; border-radius: 50%; flex: none; overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--mn-accent) 14%, transparent);
    color: var(--mn-accent); font-size: 15px; font-weight: 700; }
  /* The picture itself is partials/_avatar.html (.av-img). */
  .mnav-nm { display: block; font-family: var(--serif); font-size: 19px; color: var(--mn-ink);
    line-height: 1.2; }
  /* The label is 11px, but it is a real link, so its hit area is padded out to
     the same 44px floor the trigger uses and pulled back with a negative margin
     — the row keeps its original height, the target is thumb-sized. `flex` (not
     `inline-flex`) keeps it block-level so it stays on its own line under the
     name; `fit-content` stops it spanning the whole column. */
  .mnav-plan { display: flex; align-items: center; width: fit-content; min-height: 44px;
    margin: -14px 0; font-family: var(--mono); font-size: 11px;
    letter-spacing: .1em; text-transform: uppercase; color: var(--mn-accent); }

  /* ── Rows ─────────────────────────────────────────────────────────────────
     Spectral at 26px on a hairline, 60px tall. Apple's menu rows are the divider
     — no chevrons, no icons, no boxes. The brass rule that slides in from the
     left on press is this product's active-tab mark, borrowed. */
  .mnav-link { position: relative; display: flex; align-items: center; min-height: 60px;
    padding: 4px 2px; border-bottom: 1px solid var(--mn-line);
    font-family: var(--serif); font-weight: 300; font-size: 26px; letter-spacing: -.02em;
    color: var(--mn-ink); text-decoration: none; text-transform: none;
    transition: color .18s ease; }
  /* Sits 12px out in the gutter, not flush to the viewport edge — a mark that
     touches the bezel reads as a rendering artefact, not a mark. */
  .mnav-link::before { content: ""; position: absolute; left: -12px; top: 50%;
    width: 2px; height: 0; background: var(--mn-accent); transform: translateY(-50%);
    transition: height .22s cubic-bezier(.22,1,.36,1); }
  .mnav-link:hover, .mnav-link:focus-visible { color: var(--mn-accent); outline: none; }
  .mnav-link:hover::before, .mnav-link:focus-visible::before { height: 30px; }
  .mnav-link[aria-current="page"] { color: var(--mn-accent); }
  .mnav-link[aria-current="page"]::before { height: 30px; }
  .mnav-link.danger { font-family: var(--mono); font-size: 13px; letter-spacing: .1em;
    text-transform: uppercase; color: var(--mn-faint); border-bottom: 0; min-height: 54px; }
  .mnav-link.danger:hover, .mnav-link.danger:focus-visible { color: var(--crit, #e0796b); }
  .mnav-link.danger:hover::before, .mnav-link.danger:focus-visible::before { background: var(--crit, #e0796b); }
  .mnav-out { margin: 0; }
  .mnav-out button { width: 100%; background: none; border: 0; padding: 4px 2px;
    text-align: left; cursor: pointer; }

  /* ── Preference rows (signed-in sheet only) ───────────────────────────────
     Below 900px the topbar hides both the appearance strip and the privacy eye,
     so they land here or they are unreachable on a phone.

     These are settings, not destinations, so they take the mono label the
     sign-out row uses rather than the 26px Spectral of a place you can go. Same
     hairline, same rhythm; a smaller voice for a switch than for a door. No
     brass gutter rule either — that mark means "you are here", and a toggle is
     not somewhere you are. */
  .mnav-pref { display: flex; align-items: center; justify-content: space-between;
    gap: 16px; width: 100%; min-height: 60px; padding: 4px 2px;
    border-bottom: 1px solid var(--mn-line);
    background: none; border-left: 0; border-right: 0; border-top: 0;
    text-align: left; }
  .mnav-pref-btn { cursor: pointer; }
  .mnav-pref-lb { font-family: var(--mono); font-size: 13px; letter-spacing: .1em;
    text-transform: uppercase; color: var(--mn-faint); transition: color .18s ease; }
  .mnav-pref-btn:hover .mnav-pref-lb,
  .mnav-pref-btn:focus-visible .mnav-pref-lb { color: var(--mn-accent); }

  /* Icon plus the word, because a lone eye on a row this wide is a guess. The
     word is what changes colour when it is on: brass is the product's "this is
     live" everywhere else. */
  .mnav-pv { display: inline-flex; align-items: center; gap: 9px; flex: none;
    font-family: var(--mono); font-size: 11.5px; letter-spacing: .1em;
    text-transform: uppercase; color: var(--mn-faint); }
  .mnav-pv svg { width: 17px; height: 17px; }
  .mnav-pv em { font-style: normal; }
  html[data-privacy="on"] .mnav-pv { color: var(--mn-accent); }

  /* ── Foot ─────────────────────────────────────────────────────────────────
     The one action, pinned to the bottom of the sheet where a thumb already is.
     44px is the hero rung of the app's button ladder (.btn-lg), not a height of
     its own: this is the one hero action on the sheet, so it uses the height the
     rest of the product gives a hero action. Self-styled rather than .btn-lg
     because two of the four surfaces that render this sheet never load app.css. */
  .mnav-foot { flex: none; padding: 20px 22px calc(24px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--mn-line); }
  .mnav-cta { display: flex; align-items: center; justify-content: center; gap: 9px;
    width: 100%; height: 44px; border-radius: 8px;
    background: var(--mn-accent); border: 1px solid var(--mn-accent); color: var(--mn-on-accent);
    font-family: var(--mono); font-size: 14px; font-weight: 500; letter-spacing: 0;
    cursor: pointer; transition: filter .16s ease, transform .1s ease; }
  .mnav-cta:hover { filter: brightness(1.08); }
  .mnav-cta:active { transform: scale(.985); }
  .mnav-cta:focus-visible { outline: 2px solid var(--mn-accent); outline-offset: 3px; }
  .mnav-cta .gh { width: 16px; height: 16px; fill: currentColor; stroke: none; flex: none; }

  /* ── Entrance ─────────────────────────────────────────────────────────────
     Rows rise in sequence rather than all at once: the stagger is what makes a
     sheet feel like it opened instead of appeared. Delays are set inline per row
     so the count is whatever the caller passed. */
  .mnav[data-open="true"] .mnav-rise { animation: mnavRise .42s cubic-bezier(.22,1,.36,1) backwards; }
  @keyframes mnavRise { from { opacity: 0; transform: translateY(12px); } }
  @media (prefers-reduced-motion: reduce) {
    .mnav { transition: opacity .01s linear, visibility .01s; }
    .mnav[data-open="true"] .mnav-rise { animation: none; }
    .mnav-bars i { transition: none; }
    .mnav-link::before { transition: none; }
  }

  /* Locks the page behind the sheet. Set on <html> so iOS Safari honours it. */
  html.mnav-lock, html.mnav-lock body { overflow: hidden; }

  /* A short landscape phone cannot afford 26px rows and 60px of height each. */
  @media (max-height: 520px) {
    .mnav-top { height: 60px; }
    .mnav-link { min-height: 48px; font-size: 21px; }
    .mnav-id { padding: 14px 0 16px; }
  }
