/* member.css — the branch screen.
 *
 * Read by older staff, on a phone, often outdoors. Everything below follows from
 * that:
 *
 *   - CONTENT is sized in rem. The font-size control sets ONE property on <html>
 *     and the whole screen — type, padding, gaps, cards, the nav — grows with it.
 *     A px value in the content would refuse to scale and break at the largest
 *     size.
 *     The one deliberate exception is the font-size control itself, which is
 *     pinned to 44px. It is chrome, not content: at the largest size a scaling
 *     control plus the wordmark wanted ~414px of a 375px screen and collided.
 *     44px is the touch-target floor, so pinning it costs nothing and keeps the
 *     control reachable at every size. The letters inside it still scale.
 *   - Media queries stay in px on purpose: they ignore the root font-size, so
 *     the breakpoints do not move when a user scales up.
 *   - Colour is never the only signal. Every price move also carries an arrow,
 *     a word, and the amount.
 *   - Nothing is hidden behind a menu. Two destinations, both always visible.
 */

/* ------------------------------------------------------------- font scale */
/* The three steps the A / A / A control sets. Applied by a blocking script in
   <head> before first paint, so nobody sees text jump size on load. */
html { font-size: 100%; }                  /* 16px — Standard */
html[data-fs="s"] { font-size: 100%; }     /* 16px */
html[data-fs="m"] { font-size: 118.75%; }  /* 19px — the default: these users are older */
html[data-fs="l"] { font-size: 137.5%; }   /* 22px — Largest */

body {
  font-size: 1rem;
  line-height: 1.5;
  background: var(--bg);
  padding-bottom: 5.5rem; /* clears the fixed bottom nav */
}

/* ---------------------------------------------------------------- header */

/* Deliberately NOT sticky.
 *
 * It holds a wordmark and two controls a reader sets once and never touches
 * again. Pinned, it cost 212px — 26% of the screen — permanently, and at the
 * largest text size that left room for barely two prices. It also sat on top of
 * .m-chips (also sticky at top:0, but lower z-index), so the category filter
 * slid underneath it and was never actually visible while scrolling.
 *
 * Letting it scroll away gives the screen back to the prices AND lets the chips
 * do the sticking — which is the thing worth pinning in a 34-row list.
 */
.m-head {
  background: var(--navy); color: #fff;
  padding: .8rem 1rem;
  padding-top: calc(.8rem + env(safe-area-inset-top, 0px));
}
.m-head-top { display: flex; align-items: center; justify-content: space-between; gap: .75rem; flex-wrap: wrap; }
/* Font-size + language wrap together, not one-at-a-time. Without this, at
   ~375px viewport the language picker was the odd item out and dropped to
   its own row while the size picker stayed beside the brand — the two
   visually-identical chips ending up on different rows.
   margin-left:auto pushes the group right when it lands on its own row
   (justify-content: space-between only spaces items when there is more than
   one on a row). Desktop still puts brand-left/controls-right in a single row. */
.m-head-controls { display: flex; gap: .5rem; flex: none; margin-left: auto; }
.m-brand { display: flex; align-items: center; gap: .5rem; min-width: 0; flex: 1 1 auto; }
/* Height-driven: the mark is 1.46:1, so a square box would squash the mountain. */
.m-brand img { height: 1.6rem; width: auto; flex: none; }
/* The wordmark yields before the control does — the control is the useful one. */
.m-brand b { font-size: 1.05rem; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.m-branch { margin-top: .5rem; }
.m-branch b { display: block; font-size: 1.5rem; letter-spacing: -.02em; line-height: 1.2; }
.m-branch span { display: block; color: #a9c8e6; font-size: .85rem; margin-top: .1rem; }
/* Second, quieter line: when the list was last published. Same #a9c8e6 (6.6:1
   on the navy — legible to an older reader outdoors); only the size steps down.
   Keep the compound selector: it must beat .m-branch span's font-size. */
.m-branch .m-when { font-size: .8rem; margin-top: .15rem; }

/* One radius for small controls. Cards stay .8rem; chips stay 999px pills. */
:root { --radius-ctl: .5rem; }

/* Font-size control: three real letters at ascending size, so the control shows
   what it does. In the header, not buried in a settings screen.
   Quiet chrome — no group box. The active choice is white with a 3px underline
   (a shape, not just a colour, so it survives red-green colour blindness), the
   same idiom the bottom nav already uses. Every button reserves the underline
   so nothing shifts when the choice moves. */
.fs-ctl { display: flex; gap: .15rem; flex: none; }
.fs-ctl button {
  /* Pinned in px, deliberately — see the note at the top of this file. 44px is
     the touch-target floor, and a control that grew with the text collided with
     the wordmark at the largest size. The letters inside still scale. */
  min-width: 44px; min-height: 44px;
  border: none; border-bottom: 3px solid transparent; background: none; color: #cfe0f0;
  border-radius: var(--radius-ctl); cursor: pointer; font-family: inherit; font-weight: 700;
  display: flex; align-items: center; justify-content: center; padding: 0 .3rem;
}
.fs-ctl button[data-size="s"] { font-size: .8rem; }
.fs-ctl button[data-size="m"] { font-size: 1rem; }
.fs-ctl button[data-size="l"] { font-size: 1.25rem; }
.fs-ctl button.on { color: #fff; border-bottom-color: #fff; }
.fs-ctl button:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

/* Language picker: same quiet shape as the text size, deliberately. A hairline
   keeps the two clusters legible as two now that the boxes are gone. Each
   option is written in its own language, so you can find yours without being
   able to read the other two. */
.lang-ctl { border-left: 1px solid rgba(255, 255, 255, .25); padding-left: .35rem; }
.lang-ctl button { font-size: .85rem; font-weight: 700; padding: 0 .5rem; }
.lang-ctl button[lang="zh"] { font-size: .95rem; }

/* Today/Tomorrow — a data switch, not chrome, so it KEEPS the boxed segmented
   look the header controls gave up. Which day's prices you are quoting must be
   unmissable (the failure mode is quoting tomorrow's price today), and this
   control only appears once HQ has published tomorrow — exactly when it must
   not be overlooked. Its own class also ends the old fragility of inline-
   overriding .fs-ctl. */
.day-ctl {
  display: inline-flex; gap: .25rem; margin-top: .6rem;
  background: rgba(255, 255, 255, .12); border-radius: var(--radius-ctl); padding: .2rem;
}
.day-ctl button {
  min-width: 44px; min-height: 44px; border: none; background: none; color: #cfe0f0;
  border-radius: var(--radius-ctl); cursor: pointer; font-family: inherit;
  font-weight: 700; font-size: .95rem; padding: 0 .8rem;
  display: flex; align-items: center; justify-content: center;
}
.day-ctl button.on { background: #fff; color: var(--navy); }
.day-ctl button:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

/* ------------------------------------------------------------------ chips */

/* The one thing worth pinning: 34 rows scroll past, and the reader needs to be
   able to jump to Battery without scrolling back to the top. Now that .m-head
   is not sticky, this actually stays visible. */
.m-chips {
  display: flex; gap: .45rem; overflow-x: auto; padding: .7rem 1rem;
  background: #fff; border-bottom: 1px solid var(--line);
  position: sticky; top: env(safe-area-inset-top, 0px); z-index: 10;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.m-chips::-webkit-scrollbar { display: none; }
.m-chip {
  flex: none; min-height: 2.75rem; padding: .4rem 1rem;  /* 44px at the smallest scale */
  border: 1.5px solid var(--line-strong); background: #fff; color: var(--text);
  border-radius: 999px; font-family: inherit; font-size: .95rem; font-weight: 600;
  cursor: pointer; white-space: nowrap;
}
.m-chip.on { background: var(--navy); border-color: var(--navy); color: #fff; }
.m-chip:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }

/* ------------------------------------------------------------- price list */

.m-list { padding: .75rem .75rem 1rem; display: flex; flex-direction: column; gap: .5rem; }
/* Said once at the top of the list, so 33 rows do not each repeat it.
   margin:0 is load-bearing — styles.css has no <p> reset. */
.m-list-note { margin: 0; padding: .1rem .25rem 0; font-size: .8rem; color: var(--muted); }
.m-cat { font-size: .8rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); padding: .75rem .25rem .1rem; }

.m-row {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  background: var(--card); border: 1px solid var(--line); border-radius: .8rem;
  padding: .8rem .9rem; min-height: 3.5rem;
  width: 100%; text-align: left; font-family: inherit; color: inherit; cursor: pointer;
}
.m-row:active { background: var(--blue-tint); }
.m-row:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
/* The name column yields; the price column never shrinks or wraps. */
.m-row-l { display: block; flex: 1 1 auto; min-width: 0; }
.m-row-r { display: block; flex: 0 0 auto; text-align: right; }
.m-row-name { display: block; font-size: 1.05rem; font-weight: 600; line-height: 1.3; }
.m-row-sub { display: block; font-size: .8rem; color: var(--faint); margin-top: .1rem; }

/* The number is the whole point of the screen — it is the biggest thing on it. */
.m-price { display: block; font-size: 1.45rem; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.15; white-space: nowrap; }
.m-price small { font-size: .62em; font-weight: 700; opacity: .55; margin-right: .18em; }

.m-move { display: inline-flex; align-items: center; gap: .2rem; margin-top: .2rem; font-size: .85rem; font-weight: 700; padding: .1rem .4rem; border-radius: var(--radius-ctl); font-variant-numeric: tabular-nums; white-space: nowrap; }
.m-move.up { color: var(--up); background: var(--up-bg); }
.m-move.down { color: var(--down); background: var(--down-bg); }
.m-move.same { color: var(--same); background: var(--same-bg); }
.m-move.new { color: var(--new); background: var(--new-bg); }
.m-move.unpriced { color: var(--faint); }
.m-row.is-unpriced .m-price { color: var(--faint); font-size: 1.05rem; font-weight: 600; }

/* -------------------------------------------------------------- bottom nav */

.m-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  display: flex; background: #fff; border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0px);  /* iPhone home indicator */
  box-shadow: 0 -2px 12px rgba(20, 42, 69, .06);
}
.m-nav button {
  flex: 1; min-height: 3.5rem;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .1rem;
  border: none; background: none; cursor: pointer; font-family: inherit;
  color: var(--muted); font-size: .8rem; font-weight: 700; padding: .5rem;
  border-top: 3px solid transparent; margin-top: -1px;
}
.m-nav button .ico { font-size: 1.2rem; line-height: 1; }
.m-nav button.on { color: var(--blue); border-top-color: var(--blue); }
.m-nav button:focus-visible { outline: 3px solid var(--blue); outline-offset: -3px; }

/* ---------------------------------------------------------------- history */

.m-sheet { padding: .75rem; }
.m-card { background: var(--card); border: 1px solid var(--line); border-radius: .8rem; padding: 1rem; }
.m-card + .m-card { margin-top: .6rem; }
.m-card h2 { margin: 0 0 .1rem; font-size: 1.15rem; }
.m-card .sub { color: var(--muted); font-size: .85rem; margin: 0 0 .75rem; }

.m-pick { width: 100%; min-height: 3rem; padding: .5rem .7rem; font: inherit; font-size: 1rem; border: 1.5px solid var(--line-strong); border-radius: var(--radius-ctl); background: #fff; color: var(--text); }
.m-pick:focus { outline: 3px solid var(--blue); outline-offset: 1px; }

.m-hist-row { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .65rem .25rem; border-bottom: 1px solid var(--line); }
.m-hist-row:last-child { border-bottom: none; }
.m-hist-row .d { font-size: .95rem; font-weight: 600; min-width: 0; }
/* The price never wraps: at the largest text size a long date label would
   otherwise push "RM 50.00" onto two lines. The date yields instead. */
.m-hist-row .v { font-size: 1.1rem; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; flex: none; }

/* From/To range — only rendered in Custom mode.
   Wraps to stacked at the largest text size rather than crushing two date
   inputs onto one line: 9rem scales with the font control, so the break point
   follows the reader rather than a fixed pixel width. */
.m-range { display: flex; gap: .6rem; flex-wrap: wrap; padding: .75rem 0 0; }
.m-range label { flex: 1 1 9rem; min-width: 9rem; }
.m-range label > span { font-size: .85rem; font-weight: 700; color: var(--muted); display: block; margin-bottom: .35rem; }
.m-range-note { color: var(--muted); font-size: .8rem; margin: .6rem 0 0; }

.m-empty { text-align: center; padding: 3rem 1.25rem; color: var(--muted); }
.m-empty b { display: block; font-size: 1.15rem; color: var(--text); margin-bottom: .35rem; }

/* ------------------------------------------------------------------- misc */

.m-note { background: var(--blue-tint); border: 1px solid #c8ddf3; color: #1c4470; border-radius: var(--radius-ctl); padding: .7rem .85rem; font-size: .8rem; line-height: 1.55; margin: .75rem; }
.m-note b { display: block; }

/* Wider phones and tablets: the list would otherwise stretch to silly widths. */
@media (min-width: 700px) {
  .m-head, .m-chips { padding-left: max(1rem, calc(50vw - 21rem)); padding-right: max(1rem, calc(50vw - 21rem)); }
  .m-list, .m-sheet, .m-note { max-width: 44rem; margin-left: auto; margin-right: auto; }
}
