/* The phone. One file, linked by every page, so the three cannot drift.
 *
 * **Measured before it was written.** On a 390px viewport the site had no
 * theme-color, no manifest, no safe-area handling, and TWELVE tap targets under
 * 44px - the timeframe pills were 35px and one control was 24px. The page was
 * 2648px tall with the call buttons far below the fold, and there was no way to
 * reach the account without scrolling to the top and finding a link.
 *
 * **Everything here is additive and phone-only.** The desktop layout is already
 * what the design docs describe; this is the layer that makes it hold in a hand.
 * Nothing below 640px overrides a rule the wider layout depends on.
 */

/* ── things that are wrong on a phone at any width ─────────────────────── */

html {
  /* Safari bumps font sizes on rotate unless told not to, which reflows a
     chart mid-round. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  /* Rubber-banding at the top of a page chains to the document behind it in a
     standalone window and looks like the app has come loose. */
  overscroll-behavior-y: contain;
}

/* **No 300ms wait and no grey flash.** Both are what makes a web page feel like
   a web page: the browser holds a tap to see whether it becomes a double-tap,
   and paints a translucent box over whatever was pressed. `touch-action`
   removes the wait; the highlight is replaced below by a transform a native
   control would use. */
a, button, summary, input, select, label, [role="button"] {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

@media (hover: none) {
  /* **Pressed state instead of hover.** A phone has no hover, so a control that
     only responds to it gives no feedback at all between the tap and whatever
     happens next - which on a slow network is the whole interaction. */
  button:active, a:active, summary:active, .act:active,
  .copy:active, .go:active, .signin-way:active, .wallet:active {
    transform: scale(.985);
    opacity: .9;
  }
}

/* ── the safe areas ───────────────────────────────────────────────────── */

/* Needs `viewport-fit=cover` in the viewport meta, or the insets are all zero
   and this does nothing. */
@supports (padding: env(safe-area-inset-left)) {
  .wrap, .shell, main {
    padding-left: max(20px, env(safe-area-inset-left));
    padding-right: max(20px, env(safe-area-inset-right));
  }
}

/* ── one thumb ────────────────────────────────────────────────────────── */

@media (max-width: 640px) {
  /* **44px, which is the floor both platforms publish.** Twelve controls were
     under it, and the ones a reader uses most - the timeframe pills and the
     candle-count buttons - were the smallest. The visual size is unchanged
     where it matters; the touch area is grown with padding so the row does not
     suddenly become chunky. */
  button, .act, .copy, .go, .signout, .chip, summary, select,
  input:not([type="checkbox"]):not([type="radio"]) {
    min-height: 44px;
  }
  /* **A link inside a sentence is not a control.** "…on <a>your account</a>."
     is prose, and giving it a 44px box would push the line apart and leave a
     tall invisible target in the middle of a paragraph. The floor is for things
     a reader aims at, and an inline link is aimed at with a word. */
  p a, li a, .note a, small a { min-height: 0; }
  /* A pill row keeps its look: the height comes from padding, not from a
     bigger font. */
  .tf button, .count button, .act, .chip {
    padding-top: 11px;
    padding-bottom: 11px;
  }

  /* **The custom amount is a field INSIDE a pill, so the floor above landed on
     both and stacked**: a 60px pill sitting in a row of 44px buttons, 8px off
     the line they share. The pill is the thing a thumb aims at, so it carries
     the 44 and the field inside it gives up its own. Measured at 390px. */
  .real-amt-other { padding-top: 0; padding-bottom: 0; min-height: 44px; }
  .real-amt-other input { min-height: 0; }

  /* Inputs at 16px or Safari zooms the whole page when one is focused, and
     never zooms back. */
  input, select, textarea { font-size: 16px; }

  /* A table wider than the screen is a horizontal scrollbar inside a vertical
     one, which nothing on a phone expects. Anything left that is a real table
     scrolls on its own rather than pushing the page sideways. */
  .card table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* ── two triggers, and they mean different things ─────────────────────────
 *
 * `.is-phone` is "the server chose the phone template" - see src/device.js. It
 * is on /account, /account/notifications and /account/about, which are all
 * `no-store`, so their body may safely depend on the user-agent.
 *
 * `@media (max-width: 640px)` is "this window is narrow, whoever is looking".
 * The landing page is edge-cached with `s-maxage=60` and Cloudflare does not
 * honour `Vary` on HTML, so that page cannot be forked on the server without
 * handing one reader's layout to the next. It stays responsive by width.
 *
 * `body:not(.is-wide)` is what makes the "Desktop version" toggle actually win:
 * without it the media query would drag a reader who asked for the wide layout
 * straight back to the phone one.
 */

/* ── the width a phone actually has ───────────────────────────────────── */

@media (max-width: 640px) {
  /* **The screenshot that prompted this had gutters down both sides.** The wrap
     pads 20px, then every card pads again and draws a border, so a 390px screen
     was spending ~70px on nothing before any content. On a phone the page IS the
     card - the border is what the screen edge already does. */
  body:not(.is-wide) .wrap { padding-left: 12px; padding-right: 12px; padding-top: 0; }
  /* **The landing page pads twice.** `body` pads 20px and `main` pads 20px
     inside it, so a 390px screen spent 80px - a fifth of the width - before any
     content, which is the same fault as the card-inside-a-card below and was
     invisible until the header was measured. The inset stays on the inner one,
     because that is the element the safe-area rule targets. */
  body:not(.is-wide) { padding-left: 0; padding-right: 0; }
  body:not(.is-wide) main, body:not(.is-wide) .shell {
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
  }
  body:not(.is-wide) .card {
    padding-left: 14px;
    padding-right: 14px;
    border-radius: 14px;
  }
  /* A card inside a card is two borders and two paddings for one idea. The
     round widget did this: the stat block sat in its own box inside the widget's
     box, and both were inside the wrap. */
  body:not(.is-wide) .card .card,
  body:not(.is-wide) .card .acct-stats {
    border: 0;
    padding-left: 0;
    padding-right: 0;
    background: none;
  }
  /* The readouts keep their panel - they are the one block that reads as a
     group - but lose the extra inset. */
  body:not(.is-wide) .acct-stats { padding-left: 12px; padding-right: 12px; }
}

/* ── the readouts ─────────────────────────────────────────────────────── */

.is-phone .acct-stats {
  /* **Five equal readouts, two at a time.** Across a 390px screen they were five
     columns of about 60px, which is not enough for "$1,234.56" and was truncating
     the one figure a reader opens this page for. Two columns keeps the tile shape
     docs/design.md sets out - label above, value below - and keeps all five the
     same size, so nothing here claims a hierarchy the data does not have. */
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px 0;
}

/* Five into two leaves one over. It spans rather than sitting in a half-empty
   row, because a lone tile beside a gap reads as a missing sixth. */
.is-phone .acct-stat:last-child { grid-column: 1 / -1; }

/* ── a table is not a table on a phone ────────────────────────────────── */

/* **The seven-column tables were the worst thing on the phone page.** Positions
   and trades both scrolled sideways inside a page that scrolls down, so the
   Result column - the one a reader opens the page to see - was off-screen and
   nothing said so.
 *
 * One renderer, two presentations. Each cell carries the name of its column in
 * `data-k` (see cell() in account.js) and here that becomes a label beside the
 * value, so a row is a card. The alternative was a second renderer for phones,
 * and two implementations of one thing is how this repo got two round widgets
 * that had drifted four ways nobody chose. */

.is-phone .card table {
  display: block;
  /* No sideways scroll left to do: the cards fit. */
  overflow-x: visible;
  border-collapse: separate;
}

/* The head is the labels, and the labels are now on the cells. */
.is-phone .card table thead { display: none; }
.is-phone .card table tbody { display: block; }

.is-phone .card tbody tr {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 12px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}
.is-phone .card tbody tr:first-child { border-top: 0; padding-top: 4px; }

.is-phone .card tbody td {
  display: block;
  padding: 0;
  border: 0;
  font-size: 15px;
  line-height: 1.25;
  /* A long market title must wrap rather than push the grid wider than the
     screen. `minmax(0, …)` is what a grid column needs for that, and `1fr` alone
     is not it. */
  min-width: 0;
  overflow-wrap: anywhere;
}

/* The column name, 11px, above the value - the same tile shape as the readouts
   above and as the round widget, so the page reads as one product. */
.is-phone .card tbody td[data-k]::before {
  content: attr(data-k);
  display: block;
  font-size: 11px;
  letter-spacing: .02em;
  color: var(--muted);
  margin-bottom: 2px;
}

/* The market titles its own card, so it takes the full width and goes first.
   `order` rather than a different cell order in the renderer, so the wide
   layout's columns still line up with its thead. */
.is-phone .card tbody td.cardhead {
  grid-column: 1 / -1;
  order: -1;
  font-weight: 600;
  font-size: 15px;
}

/* The message inside that heading is prose, not a value, so it keeps its own
   weight and colour rather than inheriting the heading's. */
.is-phone .card tbody td.cardhead .notif-msg { font-weight: 400; }

/* **The last column is the answer, and it gets the width.** On both tables that
   is Result - how the round ended on a trade, and Running-with-a-Sell-button or
   Won-to-claim on a position. In a two-column grid it landed in a half-width
   slot with a gap beside it, which is the one cell that should not be cramped.
   Structural rather than by label, so renaming a column cannot silently undo it. */
.is-phone .card tbody td:last-child { grid-column: 1 / -1; }

/* "Nothing here yet" and "we could not ask" are one sentence, not a cell. */
.is-phone .card tbody td.empty {
  grid-column: 1 / -1;
  font-size: 13px;
  color: var(--muted);
}

/* A control inside a row is a control, not a line of text. */
.is-phone .card tbody td button { margin-left: 0; margin-top: 6px; }

/* ── the folds ────────────────────────────────────────────────────────── */

.is-phone .fold > summary {
  /* A whole-width row to press, which is what a phone offers for a disclosure.
     The heading inside it was the only target before. */
  padding: 12px 2px;
  align-items: center;
}
.is-phone .fold > summary h2 { font-size: 1rem; margin: 0; }
.is-phone .fold-body { padding-left: 0; padding-right: 0; }

/* ── the bottom bar ───────────────────────────────────────────────────── */

/* **Where a thumb is.** Four destinations fixed to the bottom, which is where
   every application on the device puts them. The markup is only sent to the
   phone template - see src/account-chrome.js - so this is what styles it, and
   the media query below is for the landing page, which cannot be forked on the
   server. */
.tabbar {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  /* The blur is what makes content passing underneath read as depth rather
     than as a rendering fault. Plain panel colour where it is unsupported. */
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  backdrop-filter: saturate(1.6) blur(14px);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
.tabbar a {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 52px;
  text-decoration: none;
  font-size: 11px;
  color: var(--muted);
}
.tabbar a[aria-current="page"] { color: var(--up); font-weight: 600; }
.tabbar svg { width: 21px; height: 21px; display: block; }
.tabbar a:active { opacity: .6; transform: none; }

.is-phone .tabbar { display: flex; }
/* The bar floats over the page, so the page ends above it. Without this the
   last control on every screen is unreachable. */
.is-phone { padding-bottom: calc(56px + env(safe-area-inset-bottom)); }

@media (max-width: 640px) {
  body:not(.is-wide) .tabbar { display: flex; }
  body:not(.is-wide) { padding-bottom: calc(56px + env(safe-area-inset-bottom)); }
}

/* ── the header, on a phone ───────────────────────────────────────────── */

.is-phone header.top,
body:not(.is-wide) header.top {
  /* The account header was four rows before the first number. It is one row
     that stays put, so the address and the way out are always reachable without
     scrolling back up. */
  position: sticky;
  top: 0;
  z-index: 30;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  padding-top: max(8px, env(safe-area-inset-top));
  padding-bottom: 8px;
  margin-bottom: 14px;
}

/* Sticky only where the window is actually narrow. On a desktop that asked for
   the phone template the rules above still apply; on a wide window that did
   not, none of this should. */
@media (min-width: 641px) {
  body:not(.is-phone) header.top { position: static; padding-top: 0; }
}

.is-phone header.top {
  /* One row: the mark, the page name, and who you are. The wordmark and the
     build stamp are not sent to a phone at all - see functions/account.js. */
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 10px;
}
.is-phone header.top h1 { font-size: 1.15rem; margin: 0; }
/* **The address must not wrap.** `.addr` breaks anywhere, which is right for a
   full 42-character address in a paragraph and catastrophic in a one-row header:
   the short form came out as six lines of two characters and pushed the page
   43px wider than the screen. The summary shows the short form; the full one is
   inside the menu, where breaking anywhere is what it should do. */
.is-phone header.top .who-menu > summary .addr {
  white-space: nowrap;
  word-break: normal;
  overflow-wrap: normal;
}
.is-phone header.top .who { margin: 0; justify-self: end; }
.is-phone header.top .lede, .is-phone header.top .sub { grid-column: 1 / -1; }

@media (max-width: 640px) {
  body:not(.is-wide) header.top h1 { font-size: 1.15rem; }
  /* The build stamp is for a support conversation, and it is in the identity
     menu as well. On a phone it is spending width the title needs. */
  body:not(.is-wide) header.top h1 .ver { display: none; }
  body:not(.is-wide) .acct-tabs { display: none; }
}

/* ── the front page, on a phone ───────────────────────────────────────── */

@media (max-width: 640px) {
  /* **The widget starts higher.** The hero and its paragraph filled the whole
     first screen, so a reader who came to call a candle had to scroll past
     copy they have already read to reach the thing they came for. The words do
     not change - the type scale does, which is a phone reading distance rather
     than a desktop one. */
  body:not(.is-wide) h1 { font-size: clamp(1.75rem, 8vw, 2.1rem); line-height: 1.15; }
  body:not(.is-wide) .lede, body:not(.is-wide) .sub { font-size: .95rem; }

  /* **The landing page's header is `.topbar`, not `.top`.** It had a rule aimed
     at `header.top .mark b` that matched nothing here - that selector belongs to
     the account pages, and the difference had been invisible because a rule that
     matches nothing looks exactly like a rule that had no effect.
     `.topbar` wraps by default, so the wordmark took one row and "Connect
     wallet" the next: about 50px above the fold on the page whose whole job is
     to get a reader to the widget. One row, mark left, button right. */
  .topbar { flex-wrap: nowrap; }
  /* The wordmark gives up width first and ends in an ellipsis; the mark itself
     never shrinks. Without `flex: none` on the svg it went from 22px to 5px -
     a flex item shrinks below its own width unless told not to, and a logo the
     size of a full stop is worse than no logo. */
  .topbar .brand {
    font-size: .82rem;
    letter-spacing: .06em;
    min-width: 0;
    overflow: hidden;
  }
  .topbar .brand > svg, .topbar .brand > img { flex: none; }
  /* **The build stamp is not part of the wordmark.** `#264 e0d3d02` is 93px of
     a 390px header and it pushed "bayes.markets" down to "BAYE…". It is a
     support detail - it is on /api/version, and it is in the identity menu on
     every account page - so on a phone it gives its width back to the name of
     the site. Only visible once deployed: the stamp is injected per request by
     stampVersion, so a local preview of the committed file never shows it. */
  .topbar .brand .ver { display: none; }
  .topbar .brand > b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* The button keeps its own width and its words on one line: "Connect wallet"
     broken across two is the one control the page is asking a reader to press. */
  .topbar .cta { margin-left: auto; flex: none; }
  .topbar .cta .connect, .topbar .cta button, .topbar .cta a { white-space: nowrap; }
}
