

/* --------------------------------------------------------------------------
   THE PAGE REGION
   Today and More are pages of their own (#tab-today, #tab-more) that draw the phone frame, so each takes the whole tab and
   does not scroll itself: its one scroller is `.ph-scroll` (ADR-0079). The banner slot sits above the page region and shows the offline
   banner on every page.
   -------------------------------------------------------------------------- */

/* Every tab that is a phone page takes the whole tab: Today, More, Search and the account, the event page, a roster, History
   and the camp. The page is placed inside it and nothing else in the tab shows (each page's own block below hides the desk's
   markup). */
html[data-mode="mobile"] .main-content-body > :is(
  #tab-today, #tab-more, #tab-search, #tab-edit.is-phone-account, #tab-events:has(> .ph-event-host), #tab-events:has(> #ph-events),
  #tab-history[data-ph-screen], #tab-injuries, #tab-follow-ups, #tab-stock, #tab-quick-references, #tab-camp-checkin, #tab-camps, #tab-square, #tab-waivers, #tab-settings
):not(.hidden),
html[data-mode="mobile"] :is(#tab-class-checkin, #tab-today-visitors):has(> .ph-screen):not(.hidden) {
  position: relative;
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   THE DESKTOP BACKSTOP
   A session that was ever mobile keeps the chrome in its tree after crossing back: the bar is rendered once. Every phone
   element therefore needs a desktop rule, not just a mobile one. (The iPad and the Fold open are desktop mode: the
   compact shell has its own rail.)
   -------------------------------------------------------------------------- */

html[data-mode="desktop"] #tab-today,
html[data-mode="desktop"] #tab-more {
  display: none;
}

html[data-mode="mobile"] .ph-live { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--color-success); box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-success) 20%, transparent); align-self: center; }
html[data-mode="mobile"] .ph-warn-text { color: var(--color-warning-ink); font-weight: 600; }

/* The count of people in: the schedule's own count box (v3.css .class-item-count, its two states and colours), at the phone's
   header-chip size (the desk's .attendance-stats-inline tally: 26px tall), so every count on the phone is one shape. */
html[data-mode="mobile"] .ph-screen .class-item-count { width: auto; min-width: 34px; height: 26px; padding: 0 6px; box-sizing: border-box; font-size: var(--text-md); font-variant-numeric: tabular-nums; }

/* ---- Today: the all-day tiles, Earlier, the Now line, the timeline ------------------------------------------- */
html[data-mode="mobile"] .ph-days { display: grid; grid-template-columns: repeat(auto-fit, minmax(136px, 1fr)); gap: 10px; }
html[data-mode="mobile"] .ph-day {
  display: grid; gap: 3px; align-content: start; padding: 14px; border: 0; border-radius: var(--radius-lg); text-align: left; color: var(--color-text);
  background: color-mix(in srgb, var(--swatch) 12%, var(--color-bg-elevated)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--swatch) 24%, transparent);
}
html[data-mode="mobile"] .ph-day:active { background: color-mix(in srgb, var(--swatch) 20%, var(--color-bg-elevated)); }
html[data-mode="mobile"] .ph-day-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
/* The two fixtures (Today's visitors, Open Gym) are a short tile: the icon and the count on one line, the name and its
   hours under them. */
html[data-mode="mobile"] .ph-day:not(.is-wide) { padding: 8px 12px; gap: 2px; }
html[data-mode="mobile"] .ph-day:not(.is-wide) .ph-day-top { margin-bottom: 2px; }
html[data-mode="mobile"] .ph-day:not(.is-wide) .ph-day-top i { width: 28px; height: 28px; }
html[data-mode="mobile"] .ph-day:not(.is-wide) .ph-day-meta:empty { display: none; }
html[data-mode="mobile"] .ph-day-top i { display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--radius-md); background: var(--swatch); color: #fff; font-size: 1.1429rem; }
/* ONE look for a count and for the small line under or beside it, wherever the phone draws one: the day tile, a place's head,
   the remaining count and the camp's strip. A count tinted in its place's colour says whose it is. */
html[data-mode="mobile"] .ph-day-top b,
html[data-mode="mobile"] .ph-place-n b,
html[data-mode="mobile"] .ph-remaining b,
html[data-mode="mobile"] .ph-camp-strip b { font: var(--ph-t-num); font-variant-numeric: tabular-nums; color: var(--color-text); }
html[data-mode="mobile"] .ph-day-top b,
html[data-mode="mobile"] .ph-place-n b { color: color-mix(in srgb, var(--swatch) 70%, var(--color-text)); }
html[data-mode="mobile"] .ph-day-meta,
html[data-mode="mobile"] .ph-place-meta,
html[data-mode="mobile"] .ph-place-n span,
html[data-mode="mobile"] .ph-remaining span { font: var(--ph-t-meta); color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-day-name { font: var(--ph-t-row); overflow-wrap: anywhere; }
/* The all-day runs (camps, long events): full width under the two fixtures, one line each, the count at the end. */
html[data-mode="mobile"] .ph-days.is-wide { grid-template-columns: minmax(0, 1fr); margin-top: 10px; }
html[data-mode="mobile"] .ph-day.is-wide { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: 12px; align-items: center; padding: 12px 14px; }
html[data-mode="mobile"] .ph-day.is-wide .ph-day-top { display: contents; }
html[data-mode="mobile"] .ph-day.is-wide .ph-day-top i { grid-row: 1 / 3; grid-column: 1; }
html[data-mode="mobile"] .ph-day.is-wide .ph-day-top b { grid-row: 1 / 3; grid-column: 3; }
html[data-mode="mobile"] .ph-day.is-wide .ph-day-name, html[data-mode="mobile"] .ph-day.is-wide .ph-day-meta { grid-column: 2; }

html[data-mode="mobile"] .ph-earlier > summary { list-style: none; display: flex; align-items: center; gap: 8px; min-height: var(--ph-ctl); padding: 0 4px; font: var(--ph-t-label); text-transform: uppercase; letter-spacing: .06em; color: var(--color-text-muted); cursor: pointer; }
html[data-mode="mobile"] .ph-earlier > summary::-webkit-details-marker { display: none; }
html[data-mode="mobile"] .ph-earlier > summary::after { content: '\F282'; font-family: bootstrap-icons; margin-left: auto; transition: transform var(--ph-t-fade); }
html[data-mode="mobile"] .ph-earlier[open] > summary::after { transform: rotate(180deg); }
html[data-mode="mobile"] .ph-earlier > .ph-tl { margin: 4px 0 6px; }

html[data-mode="mobile"] .ph-now-line { display: flex; align-items: center; gap: 8px; }
html[data-mode="mobile"] .ph-now-line::after { content: ''; flex: 1; height: 2px; border-radius: 1px; background: color-mix(in srgb, var(--color-success) 45%, transparent); }
html[data-mode="mobile"] .ph-now-pill { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border-radius: var(--radius-sm); background: var(--color-success-tint); color: var(--color-success); font: 700 var(--ph-fs-meta)/1 var(--font-sans); }

html[data-mode="mobile"] .ph-tl { display: grid; gap: 10px; }
html[data-mode="mobile"] .ph-slot { display: grid; grid-template-columns: 44px minmax(0, 1fr); gap: 10px; align-items: start; }
html[data-mode="mobile"] .ph-slot-time { padding-top: 16px; text-align: right; font: 650 var(--ph-fs-meta)/1 var(--font-sans); color: var(--color-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
html[data-mode="mobile"] .ph-slot.is-next .ph-slot-time { color: var(--color-text); }
html[data-mode="mobile"] .ph-slot-blocks { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; min-width: 0; }
html[data-mode="mobile"] .ph-block {
  display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box; min-height: 44px; padding: 6px 10px 6px 14px;
  border: 0; border-radius: var(--radius-lg); text-align: left; color: var(--color-text);
  background: color-mix(in srgb, var(--swatch) 16%, var(--color-bg-elevated)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--swatch) 55%, var(--color-border));
}
html[data-mode="mobile"] .ph-block:active { background: color-mix(in srgb, var(--swatch) 24%, var(--color-bg-elevated)); }
/* The desk schedule's three tints (v3.css .mini.is-live / .past / bare .mini): not passed yet today is the full tint
   (above), Earlier the faint one, another day none. The next hour is told by its bold names and the Now line above it. */
html[data-mode="mobile"] .ph-slot.is-next .ph-block-name { font-weight: var(--font-bold); }
html[data-mode="mobile"] .ph-tl.is-past .ph-block { background: color-mix(in srgb, var(--swatch) 5%, var(--color-bg-elevated)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--swatch) 12%, var(--color-border)); }
html[data-mode="mobile"] .ph-tl.is-past .ph-block-name { font-weight: var(--font-normal); color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-tl.is-past .ph-block-meta { display: none; }   /* the class is over: who it is for is no longer a decision */
html[data-mode="mobile"] .ph-tl.is-past .class-item-count.has-checkins { background: color-mix(in srgb, var(--class-color, var(--color-success)) 15%, var(--color-bg-elevated)); color: color-mix(in srgb, var(--color-text-secondary) 80%, var(--color-text)); }   /* v3.css: the count fades with its card; its digit stays AA on any class colour at any hour of the tone (ADR-0077) */
html[data-mode="mobile"] .ph-tl.is-quiet .ph-block { background: var(--color-bg-elevated); box-shadow: inset 0 0 0 1px var(--color-border); }
html[data-mode="mobile"] .ph-block.is-cancelled .ph-block-name { text-decoration: line-through; color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-block-body { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px; }
/* A class row reads name left, age group at the right edge just before the count, every row one size: the next hour is
   only tinted. A block, not a flex box: an ellipsis only ends a block's line, so a flex name was chopped mid-letter. */
html[data-mode="mobile"] .ph-block-name { flex: 0 1 auto; display: block; min-width: 0; font: var(--ph-t-row); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html[data-mode="mobile"] .ph-block-meta { flex: 0 0 auto; margin-left: auto; min-width: 0; text-align: right; font: var(--ph-t-meta); color: var(--color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* too long to fit beside the name (a 320px phone): it drops under it, still at the right */

/* ---- a place: the head of a class roster or a camp, tinted in its colour ------------------------------------ */
html[data-mode="mobile"] .ph-place {
  display: flex; align-items: center; gap: 12px; padding: 16px; border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--swatch) 14%, var(--color-bg-elevated)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--swatch) 24%, transparent);
}
html[data-mode="mobile"] .ph-place-name { margin: 2px 0; font: 750 var(--ph-fs-num)/1.2 var(--font-sans); letter-spacing: -.01em; overflow-wrap: anywhere; }
html[data-mode="mobile"] .ph-place-n { flex: none; display: grid; justify-items: center; gap: 2px; min-width: 64px; padding: 10px; border-radius: var(--radius-md); background: var(--color-bg-elevated); }
html[data-mode="mobile"] .ph-place.is-camp { flex-wrap: wrap; }

/* ---- the day picker sheet (foundation/date-picker-grid.js): the desk's calendar, sized for a finger --------------------- */
/* The month arrows and the days stay as drawn; a finger lands on the invisible `--ph-hit` square behind each (a day is
   under 44 wide at 320). The Today link is drawn a small button tall so it reads and presses, with the grid kept clear of its band. */
html[data-mode="mobile"] .date-picker-sheet :is(.date-nav-btn, .date-picker-cell:not(.empty), .date-picker-today-btn) { position: relative; }
html[data-mode="mobile"] .date-picker-sheet :is(.date-nav-btn, .date-picker-cell:not(.empty), .date-picker-today-btn)::after { content: ''; position: absolute; left: calc(50% - var(--ph-hit) / 2); top: calc(50% - var(--ph-hit) / 2); width: var(--ph-hit); height: var(--ph-hit); }
html[data-mode="mobile"] .date-picker-sheet .date-picker-footer { margin-top: var(--space-3); }
html[data-mode="mobile"] .date-picker-sheet .date-picker-today-btn { height: var(--ph-btn-s); padding: 0 var(--space-3); font-size: var(--ph-fs-meta); }

/* ---- the event page (mobile-event.js): the first child of #tab-events, which takes the whole tab ------------- */
html[data-mode="mobile"] #tab-events:has(> .ph-event-host) > :not(.ph-event-host),
html[data-mode="mobile"] #tab-events[data-ph-opening] > :not(.ph-event-host) { display: none; }   /* the desk's header and body wait under it, and are not shown while it loads (app.js sets data-ph-opening) */
/* ---- the Group events list (mobile-events-list.js, ADR-0267): each day a label over a card of its events -------------- */
/* The desk's header and body never show on a phone: the list's screen holds the tab until an event's page covers it. */
html[data-mode="mobile"] #tab-events > :not(.ph-event-host):not(#ph-events) { display: none; }
html[data-mode="desktop"] #ph-events { display: none; }
html[data-mode="mobile"] #ph-events .ph-row-meta { display: block; }   /* who, then how many: each its own line */
html[data-mode="mobile"] .ph-ge-count { color: var(--color-text); }
/* A row's state chips, on their own line under its meta (any phone list). */
html[data-mode="mobile"] .ph-row-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
html[data-mode="mobile"] .ph-ge-end { display: contents; }
html[data-mode="mobile"] .ph-ge-month { padding: 8px; }
html[data-mode="mobile"] .ph-row.is-muted { opacity: .6; }
html[data-mode="mobile"] #ph-events .ge-more-row { display: flex; justify-content: center; margin-top: 12px; }
/* ---- Camps (mobile-camps.js, ADR-0269): the season as rows, a camp as its warnings, details and roster by family ----- */
/* The desk's header and body never show on a phone: the phone's screen holds the tab. */
html[data-mode="mobile"] #tab-camps > :not(#ph-camps) { display: none; }
html[data-mode="desktop"] #ph-camps { display: none; }
html[data-mode="mobile"] #ph-camps .ph-row-meta { display: block; }   /* dates and coaches, then the numbers: each its own line */
html[data-mode="mobile"] .ph-camps-numbers { color: var(--color-text); }
html[data-mode="mobile"] .ph-camps-sentence { white-space: normal; font-weight: 500; }   /* a warning is a sentence: it wraps */
html[data-mode="mobile"] .ph-well.is-warn { background: var(--color-warning-tint); color: var(--color-warning-ink); }
html[data-mode="mobile"] .ph-camps-dates { color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-camps-count { margin-left: 6px; color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-camps-count b { color: var(--color-text); }
html[data-mode="mobile"] #ph-camps .ph-bar-end > .ph-feed-region, html[data-mode="mobile"] .ph-camps-end { display: contents; }
html[data-mode="mobile"] .ph-camps-door { width: 100%; height: var(--ph-ctl); justify-content: center; }
html[data-mode="mobile"] .ph-camps-details > .ph-row { min-height: 0; }
html[data-mode="mobile"] #ph-camps .ph-notice > .btn { flex: none; }
/* ---- Online Orders (mobile-orders.js, ADR-0270): Waiting and Done as rows, an order as its line cards ------------- */
html[data-mode="mobile"] #tab-square > :not(#ph-orders) { display: none; }
html[data-mode="desktop"] #ph-orders { display: none; }
html[data-mode="mobile"] #ph-orders .ph-row { align-items: flex-start; }
html[data-mode="mobile"] #ph-orders .ph-row-meta { display: block; }
html[data-mode="mobile"] #ph-orders .ph-row > .ph-chev, html[data-mode="mobile"] #ph-orders .ph-row > .ph-row-end { align-self: center; }
html[data-mode="mobile"] .ph-orders-lines { display: grid; gap: 4px; margin-top: 8px; }
html[data-mode="mobile"] .ph-orders-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 8px; }
html[data-mode="mobile"] .ph-orders-total { flex: none; font: var(--ph-t-row); font-variant-numeric: tabular-nums; }
html[data-mode="mobile"] .ph-orders-sentence { white-space: normal; font-weight: 500; }
html[data-mode="mobile"] .ph-orders-bulk, html[data-mode="mobile"] .ph-orders-apply { width: 100%; height: var(--ph-ctl); justify-content: center; }
html[data-mode="mobile"] .ph-orders-sync { margin: 0; color: var(--color-text-muted); font: var(--ph-t-meta); }
html[data-mode="mobile"] .ph-orders-other { justify-content: center; margin-top: 0; }
html[data-mode="mobile"] .ph-orders-value { display: grid; gap: 4px; justify-items: start; }
html[data-mode="mobile"] .ph-orders-days { display: flex; flex-wrap: wrap; gap: 4px; }
html[data-mode="mobile"] .ph-orders-problem { padding: 0 14px 12px; }
html[data-mode="mobile"] .ph-orders-problem .ph-row-acts { margin-top: 8px; }
html[data-mode="mobile"] .ph-orders-line.has-problem { border-color: color-mix(in srgb, var(--color-warning) 45%, var(--color-border)); }
html[data-mode="mobile"] .ph-orders-line.is-flash { box-shadow: 0 0 0 2px var(--color-warning); }
html[data-mode="mobile"] .ph-notice.is-ok { background: var(--color-success-tint); border-color: color-mix(in srgb, var(--color-success) 40%, var(--color-border)); }
html[data-mode="mobile"] .ph-notice.is-ok > i:first-child { color: var(--color-success); }
/* ---- Waivers (mobile-waivers.js, ADR-0271): the three lists as rows, a waiver as who it covers and who signed -------- */
html[data-mode="mobile"] #tab-waivers > :not(#ph-waivers) { display: none; }
html[data-mode="desktop"] #ph-waivers { display: none; }
html[data-mode="mobile"] #ph-waivers .ph-row { align-items: flex-start; }
html[data-mode="mobile"] #ph-waivers .ph-row-meta { display: block; }
html[data-mode="mobile"] #ph-waivers .ph-row > .ph-chev, html[data-mode="mobile"] #ph-waivers .ph-row > .ph-row-end { align-self: center; }
html[data-mode="mobile"] #ph-waivers .ph-bar-end > .ph-feed-region { display: contents; }
html[data-mode="mobile"] .ph-waivers-link { width: 100%; height: var(--ph-ctl); justify-content: center; }
html[data-mode="mobile"] .ph-waivers-more { justify-content: center; }
html[data-mode="mobile"] #ph-waivers .ph-notice > .btn { flex: none; }
html[data-mode="mobile"] .ph-waivers-open { padding: 4px 14px 14px; }
html[data-mode="mobile"] .ph-waivers-open .wv-signature-img { max-width: 100%; height: auto; }
html[data-mode="mobile"] .ph-waivers-fact { display: grid; gap: 2px; margin-top: 10px; font: var(--ph-t-meta); overflow-wrap: anywhere; }
html[data-mode="mobile"] .ph-waivers-fact > span:first-child { color: var(--color-text-muted); }
html[data-mode="mobile"] .ph-waivers-note { margin: 0; color: var(--color-text-muted); font: var(--ph-t-meta); }
/* ---- Settings (mobile-settings.js, ADR-0272): the map as rows that open in place; no page opens on a phone ------- */
html[data-mode="mobile"] #tab-settings > :not(#ph-settings) { display: none; }
html[data-mode="desktop"] #ph-settings { display: none; }
html[data-mode="mobile"] .ph-settings-sentence { white-space: normal; font-weight: 500; }
html[data-mode="mobile"] .ph-settings-open { display: grid; gap: 10px; padding: 0 14px 14px; }
html[data-mode="mobile"] .ph-settings-purpose { margin: 0; font: var(--ph-t-body); }
html[data-mode="mobile"] .ph-settings-shows { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
html[data-mode="mobile"] .ph-settings-where { display: inline-flex; align-items: center; gap: 4px; font: var(--ph-t-meta); color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-settings-desk { margin: 0; display: flex; align-items: center; gap: 6px; font: var(--ph-t-meta); color: var(--color-text-muted); }
html[data-mode="mobile"] .ph-event-host { display: contents; }
/* A region the page refills (the head, the list and what is under it) lays its children out as the scroller does. */
html[data-mode="mobile"] .ph-event-part:empty { display: none; }
html[data-mode="mobile"] .ph-event-part > * + * { margin-top: var(--ph-gap); }
html[data-mode="mobile"] .ph-event-part > .ph-label + * { margin-top: 6px; }
/* The roster's own buttons (Add guest, Paste names, Match, Check in all) wrap on one line of the page. */
html[data-mode="mobile"] .ph-row-acts.is-wrap { flex-wrap: wrap; justify-content: flex-start; margin-top: 0; }
html[data-mode="mobile"] .ph-row-acts.is-wrap > .btn { flex: 1 1 auto; }
/* The Booking card: a row is a finger tall, and the phone and the email are the links. */
html[data-mode="mobile"] .ph-event-host .kv-row { min-height: var(--ph-ctl); padding-block: 0; }
html[data-mode="mobile"] .ph-event-host a.kv-v { display: flex; align-items: center; align-self: stretch; }

/* ---- the check-in sheet and the roster pages (ADR-0248, Lane C) -------------------------------------------------- */

/* A destination row in the check-in sheet: when it starts, its colour, its name and aside, and a tick that is a plus until
   the person is in. Nothing here changes size when a row is picked; the tick fills and the row tints. */
html[data-mode="mobile"] .ph-dest { gap: 10px; }
html[data-mode="mobile"] .ph-time { flex: none; width: 54px; font: 600 var(--ph-fs-meta)/1.2 var(--font-sans); color: var(--color-text-secondary); font-variant-numeric: tabular-nums; }
html[data-mode="mobile"] .ph-swatch { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--swatch, var(--color-classes)); box-shadow: 0 0 0 3px color-mix(in srgb, var(--swatch, var(--color-classes)) 18%, transparent); }
html[data-mode="mobile"] .ph-row .ph-time + .ph-swatch { margin-left: -4px; }
html[data-mode="mobile"] .ph-tick { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; border: 1.5px solid var(--color-border-strong); color: var(--color-text-muted); font-size: 1rem; }
html[data-mode="mobile"] .ph-tick.is-on { background: var(--color-success); border-color: var(--color-success); color: #fff; }
html[data-mode="mobile"] .ph-dest.is-next { background: var(--color-accent-tint); }
html[data-mode="mobile"] .ph-dest.is-dim { opacity: .5; }
html[data-mode="mobile"] .ph-dest[aria-pressed="true"] { background: color-mix(in srgb, var(--color-success) 7%, transparent); }
html[data-mode="mobile"] .ph-danger-text { color: var(--color-danger); }
html[data-mode="mobile"] .ph-in-line { display: flex; align-items: center; gap: 6px; margin-bottom: var(--ph-gap); padding: 0 4px; color: var(--color-success); font-weight: 600; }
html[data-mode="mobile"] .ph-in-line .btn { margin-left: auto; }
html[data-mode="mobile"] .ph-card > .ph-earlier > summary { min-height: 44px; padding: 0 14px; }
html[data-mode="mobile"] .ph-card > .ph-earlier[open] > summary { border-bottom: 1px solid var(--color-border-subtle); }
/* A row that opens in place (revealRow): the row is a .ph-row, its chevron turns; the hairline between two is .ph-row's. */
html[data-mode="mobile"] .ph-reveal { position: relative; }
html[data-mode="mobile"] .ph-reveal > summary { list-style: none; cursor: pointer; }
html[data-mode="mobile"] .ph-reveal > summary::-webkit-details-marker { display: none; }
html[data-mode="mobile"] .ph-reveal > summary > .ph-chev { flex: none; transition: transform var(--ph-t-fade); }
html[data-mode="mobile"] .ph-reveal[open] > summary > .ph-chev { transform: rotate(180deg); }

/* A roster page: the class tab and Today's visitors hold the phone frame in place of their desktop layout. */
html[data-mode="mobile"] :is(#tab-class-checkin, #tab-today-visitors) > :not(.ph-screen) { display: none; }
html[data-mode="mobile"] .ph-pg,
html[data-mode="mobile"] .ph-pg-body,
html[data-mode="mobile"] .ph-pg-results .search-dropin-group.on { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--ph-gap); }
html[data-mode="mobile"] .ph-pg-body:empty, html[data-mode="mobile"] .ph-pg-notices:empty, html[data-mode="mobile"] .ph-pg-results:not(:has(.on)) { display: none; }
html[data-mode="mobile"] .ph-pg-notices { display: grid; gap: var(--ph-gap); }
html[data-mode="mobile"] .ph-pg-body > .ph-label { margin-top: 8px; }
html[data-mode="mobile"] .ph-roster-banner { margin: 0; border-radius: var(--radius-lg); }
html[data-mode="mobile"] .ph-roster-banner .spacer { flex: 1; }

/* The matches replace the page body, in flow right under the field: the keyboard never covers a result, and clearing the
   field brings the roster back. The container is the desk's popover results; here it is the page, not a card over it. */
html[data-mode="mobile"] .ph-pg:has(.ph-pg-results .search-dropin-group.on) > .ph-pg-body { display: none; }
html[data-mode="mobile"] .ph-pg-results .search-dropin-group { position: static; width: auto; max-width: none; padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none; overflow: visible; }

/* The popover's own furniture (the query head, the footers, the no-account note) reads as cards here, like the rows. */
html[data-mode="mobile"] .ph-pg-results .search-dropin-group > :is(.search-mode-head, .search-result-footer, .search-dropin-note, .search-dropin-footer, .search-no-account-banner, .search-guest-fallback, .search-archived-head, .search-next-steps) { border-radius: var(--radius-lg); overflow: hidden; }

/* A roster page left in the tree by a session that crossed to desktop is hidden, never shown (it is torn down too). */
html[data-mode="desktop"] #tab-class-checkin > .ph-screen,
html[data-mode="desktop"] #tab-today-visitors > .ph-screen { display: none; }
/* ---- History: the log, a row to a line (mobile-history.js) -------------------------------------------------- */
/* The phone's screen is Activity's; while it shows, the desk's markup of the page (header, band, Activity, Reports) is out of
   the way, and Reports hides the screen to hand the page back. */
html[data-mode="mobile"] #tab-history[data-ph-screen] > :not(#ph-history) { display: none; }
html[data-mode="desktop"] #ph-history { display: none; }

/* ---- Follow-ups (ADR-0261): the call-backs as the Injuries rows, then each note whole, as the account's note cards ----- */
/* The desk's markup never shows on a phone, not even while the page's module loads (the presenter has nothing to hand back). */
html[data-mode="mobile"] #tab-follow-ups > :not(#ph-follow-ups) { display: none; }
html[data-mode="desktop"] #ph-follow-ups { display: none; }
html[data-mode="mobile"] .ph-fu-notes { display: grid; gap: 8px; }
html[data-mode="mobile"] .ph-fu-who { font: var(--ph-t-row); color: var(--color-text); }

/* ---- Quick Reference (ADR-0266): the emergency card first, then each card as a row that opens in place -------------- */
/* The desk's header and page never show on a phone, not even while the page's module loads; editing is the desk's. */
html[data-mode="mobile"] #tab-quick-references > :not(#ph-quick-ref) { display: none; }
html[data-mode="desktop"] #ph-quick-ref { display: none; }
html[data-mode="mobile"] #ph-quick-ref .ref-notice { margin-bottom: 12px; }
html[data-mode="mobile"] #ph-quick-ref .ref-emerg { margin-top: 14px; }
html[data-mode="mobile"] .ref-911 { min-height: 56px; }
/* An opened card reads as the desk's card body, inside the row's card. */
html[data-mode="mobile"] .ph-qr-body { padding: 4px 14px 14px; gap: 10px; }
html[data-mode="mobile"] .ph-qr-body .qr-details { flex-direction: row; flex-wrap: wrap; gap: 4px 14px; }
html[data-mode="mobile"] .ph-qr-handy { margin-top: 20px; }
html[data-mode="mobile"] .ph-qr-handy .ref-contact { padding-inline: 14px; }

/* ---- Injuries (ADR-0259): Report injury leads, then the search, the severity chips and the reports ---------------------- */
/* The desk's header never shows on a phone, not even for the moment the page's module loads (owner 2026-10-22: "it shows
   the older header before showing the new clean header"); the report form and window are sheets, so nothing hands it back. */
html[data-mode="mobile"] #tab-injuries > :not(#ph-injuries) { display: none; }
html[data-mode="desktop"] #ph-injuries { display: none; }
html[data-mode="mobile"] .ph-inj-report { width: 100%; margin-bottom: 12px; }
/* Where a report's call-back stands, in the Call-backs list: the desk row's words and colour (`.injury-row-due`). */
html[data-mode="mobile"] .ph-inj-due { display: block; font-weight: var(--font-medium); }   /* its own line under when and what */
html[data-mode="mobile"] .ph-inj-due.is-due { color: var(--color-paused); }
/* One report's sheet (feature/injury-detail.js) reads its record first, who, when, what and the call-back, and the two
   pictures under it: on a phone they are a scroll down, not the first screen. */
html[data-mode="mobile"] #injury-detail-modal .modal-body { display: flex; flex-direction: column; }
html[data-mode="mobile"] #injury-detail-modal .injury-band-maps { order: 1; margin: var(--space-3) 0 0; }
/* The floor plan stands upright on a phone (injury-map.js's frame) in the report form only (ADR-0262): the frame is
   the plan's turned shape, as wide as the sheet allows while the whole plan fits the screen, and the plan inside it is
   turned a quarter clockwise about its top left and slid back into the frame. A tap is read back through the turn. */
html[data-mode="mobile"] .injury-plan-frame {
  display: block; position: relative; container-type: inline-size; margin: 0 auto;
  width: min(100%, calc((100dvh - 224px) * var(--plan-h) / var(--plan-w)));
  aspect-ratio: var(--plan-h) / var(--plan-w);
}
html[data-mode="mobile"] .injury-plan-frame > .injury-plan {
  position: absolute; top: 0; left: 0;
  width: calc(100cqw * var(--plan-w) / var(--plan-h)); height: 100cqw;
  transform-origin: 0 0; transform: translateX(100cqw) rotate(90deg);
}
/* A submitted report's floor plan (ADR-0265): a square box, a third of the plan's width at its full height
   (--strip-ratio), filling the sheet's width. Close up, the picture is that third, its corner at --strip-x; the whole
   gym is the picture across the box's middle, the box unchanged. */
html[data-mode="mobile"] .injury-plan.is-zoomable {
  aspect-ratio: var(--strip-ratio) !important;
  --stage-w: 100%; --stage-h: calc(var(--strip) * 100%); --stage-x: 0%; --stage-y: calc((1 - var(--strip)) * 50%);
}
html[data-mode="mobile"] .injury-plan.is-zoomable.is-zoomed {
  --stage-w: calc(100% / var(--strip)); --stage-h: 100%;
  --stage-x: calc(var(--strip-x) / var(--strip) * -100%); --stage-y: 0%;
}
/* Its header is two lines that never wrap (detailHeader): the name and the severity chip, then the body part and the call-back. */
html[data-mode="mobile"] #injury-detail-modal .modal-title-row { flex-wrap: nowrap; }
html[data-mode="mobile"] #injury-detail-modal .modal-title-row > .modal-title { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
html[data-mode="mobile"] #injury-detail-modal .modal-title-row > .state-chip { flex: none; margin-top: 10px; }
html[data-mode="mobile"] #injury-detail-modal .modal-header-info { min-width: 0; }
html[data-mode="mobile"] #injury-detail-modal .modal-subtitle { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Its videos and photos open as their players, ready to play, full width; an Admin's Remove sits under its file. */
html[data-mode="mobile"] .injury-media-item.is-ready { display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-2); }
html[data-mode="mobile"] .injury-media-item.is-ready > .injury-media-player { order: -1; align-self: stretch; }
html[data-mode="mobile"] .injury-media-item.is-ready video,
html[data-mode="mobile"] .injury-media-item.is-ready img { width: 100%; margin-top: 0; }

html[data-mode="mobile"] .ph-feed-region:empty { display: none; }
/* A region lays its children out as the scroller does: one gap between parts, a label's own space above it. A part's own
   spacing wins (`:where`, no weight). */
html[data-mode="mobile"] :where(.ph-feed-region > :not(.ph-label) + :not(.ph-label)) { margin-top: var(--ph-gap); }
html[data-mode="mobile"] .ph-feed-find { min-width: 0; }
html[data-mode="mobile"] .ph-feed-results { margin-top: 6px; }
html[data-mode="mobile"] .ph-feed-chips { display: flex; gap: 8px; min-width: 0; }
/* A long area name ("Passes and memberships") ends in "..." inside its chip; the day chip keeps its width. */
html[data-mode="mobile"] .ph-feed-chips > .chip:last-child { min-width: 0; }
html[data-mode="mobile"] .ph-feed-chips > .chip > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-mode="mobile"] .ph-feed-when { gap: 6px; height: var(--ph-ctl-s); padding: 0 12px; border-color: var(--color-border); background: var(--color-bg-elevated); color: var(--color-text); font-weight: 600; }
/* The counts under the chips: one line, the numbers in the text colour. A count that does not fit whole wraps onto a second
   line the height hides, so a narrow phone drops the last counts and never shows half of one. */
html[data-mode="mobile"] .ph-feed-note { display: flex; flex-wrap: wrap; height: 1lh; margin: 8px 4px 0; overflow: hidden; white-space: nowrap; font: var(--ph-t-meta); color: var(--color-text-secondary); font-variant-numeric: tabular-nums; }
html[data-mode="mobile"] .ph-feed-note > span + span::before { content: '·'; margin: 0 6px; }
html[data-mode="mobile"] .ph-feed-note b { color: var(--color-text); font-weight: 600; }

/* A day is the Earlier fold's own component (.ph-earlier): its stats ride before the chevron. */
html[data-mode="mobile"] .ph-earlier > .ph-card { margin: 4px 0 6px; }
html[data-mode="mobile"] .ph-feed-stat { flex: 1; min-width: 0; text-align: right; text-transform: none; letter-spacing: 0; font: var(--ph-t-meta); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-mode="mobile"] .ph-feed-gap { padding: 6px 14px; background: var(--color-bg-subtle); color: var(--color-text-muted); font: var(--ph-t-meta); text-align: center; }

/* A row has fixed lines, each one line, so every row reads the same way at a glance; nothing wraps, a long part ends in "...":
     1  time   the name, then its chips (Waiver, New), which are short and rare     the badge, on both lines
     2         what happened · +N · the class
     3         the one plain line under it, when there is one
   A row with no badge gives its lines the whole width.
   No staff name (the entry sheet says who). Undone is struck through, never hidden. */
html[data-mode="mobile"] .ph-feed-row { display: grid; grid-template-columns: 2.75rem minmax(0, 1fr) auto; padding-left: calc(14px - (2.75rem - 2.15rem)); grid-template-areas: "time who badge" "half what badge" ". sub sub"; gap: 2px 10px; align-items: center; }
/* The time column holds the widest clock ("10:48", 37px at the meta size; in rem so the text-size setting grows both) and every
   time sits against its right edge, so the gap to the name is the same on every row. The row's left inset gives back the extra
   digit's width (2.75rem less "4:21"'s 2.15rem), so a one-digit hour, most of the day, starts 14px in like the badge ends 14px
   from the right, and "10:48"'s extra digit hangs into the inset. AM or PM sits under the clock on the what line. */
html[data-mode="mobile"] .ph-feed-time,
html[data-mode="mobile"] .ph-feed-half { grid-area: time; align-self: center; text-align: right; font: var(--ph-t-meta); font-weight: 600; color: var(--color-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
html[data-mode="mobile"] .ph-feed-half { grid-area: half; font: var(--ph-t-label); letter-spacing: .04em; }
html[data-mode="mobile"] .ph-feed-row > .ph-row-title { grid-area: who; flex-wrap: nowrap; align-self: center; }
/* The name has the whole line; the row's state chip sits whole at the end of the what line, whose words end in "...". */
html[data-mode="mobile"] .ph-feed-row > .ph-row-title > :first-child { flex: 0 0 auto; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-mode="mobile"] .ph-feed-what { grid-area: what; display: flex; align-items: center; gap: 6px; min-width: 0; font: var(--ph-t-meta); color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-feed-words,
html[data-mode="mobile"] .hx-entry-where { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-mode="mobile"] .ph-feed-row:not(:has(> .ph-feed-badge)) > :is(.ph-row-title, .ph-feed-what) { grid-column: 2 / -1; }
html[data-mode="mobile"] .ph-feed-badge { grid-area: badge; display: flex; align-items: center; justify-content: flex-end; }
html[data-mode="mobile"] .ph-feed-sub { grid-area: sub; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--ph-t-meta); color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-feed-dot { display: inline-block; width: 8px; height: 8px; margin-right: 5px; border-radius: 50%; vertical-align: 0; }
html[data-mode="mobile"] .ph-feed-row.is-undone .ph-row-title { text-decoration: line-through; color: var(--color-text-muted); }

html[data-mode="mobile"] .ph-feed-more { display: flex; justify-content: center; margin-top: var(--ph-gap); }
html[data-mode="mobile"] .ph-feed-faint { color: var(--color-text-muted); }
/* A person's log: the card's head row is the name with what they hold at its end (it opens the account), then three counts,
   each a value over its name on one line, then Back to everyone. */
html[data-mode="mobile"] .ph-feed-kvs { position: relative; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 1px solid var(--color-border-subtle); }
html[data-mode="mobile"] .ph-feed-kv { display: grid; justify-items: center; gap: 2px; min-width: 0; padding: 10px 6px; text-align: center; }
html[data-mode="mobile"] .ph-feed-kv + .ph-feed-kv { border-left: 1px solid var(--color-border-subtle); }
html[data-mode="mobile"] .ph-feed-kv > b { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--ph-t-title); font-variant-numeric: tabular-nums; }
html[data-mode="mobile"] .ph-feed-kv > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--ph-t-label); text-transform: uppercase; letter-spacing: .06em; color: var(--color-text-muted); }
html[data-mode="mobile"] .ph-feed-member > .ph-feed-kvs + .ph-row::after { display: none; }
html[data-mode="mobile"] .ph-feed-range { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
html[data-mode="mobile"] .ph-feed-lead { margin: 0; font: var(--ph-t-body); }

/* The Log entry sheet (entry-modal.js): the person's name heads it, with the time and who did it under. Each entry is a card
   that reads like its History row: an icon well, what happened (one line) over where it was (one line), the badge at the
   end; then its facts as label and value rows, one per line, as the account's Personal card has them. The footer is one row
   of the doors (Account, Class, Order) and Delete closes the body. */
html[data-mode="mobile"] .hx-entry-card { padding: 0 16px; border: 1px solid var(--color-border); border-radius: var(--ph-r-card); background: var(--color-bg); }
html[data-mode="mobile"] .hx-entry-card + .hx-entry-card { margin-top: 10px; }
html[data-mode="mobile"] .hx-entry-top { display: grid; grid-template-columns: 36px minmax(0, 1fr) auto; gap: 12px; align-items: center; min-height: 64px; padding: 10px 0; }
html[data-mode="mobile"] .hx-entry-icon { display: grid; place-items: center; width: 36px; height: 36px; border-radius: var(--radius-md); background: var(--color-bg-subtle); color: var(--color-text-secondary); font-size: 1.1429rem; }
html[data-mode="mobile"] .hx-entry-what { display: grid; gap: 2px; min-width: 0; }
html[data-mode="mobile"] .hx-entry-what > b { font: var(--ph-t-row); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-mode="mobile"] .hx-entry-meta { display: flex; align-items: center; gap: 6px; min-width: 0; height: 22px; overflow: hidden; font: var(--ph-t-meta); color: var(--color-text-secondary); }
html[data-mode="mobile"] .hx-entry-meta > :not(.hx-entry-where) { flex: none; }
html[data-mode="mobile"] .hx-entry-dot { display: inline-block; width: 8px; height: 8px; margin-right: 5px; border-radius: 50%; }
html[data-mode="mobile"] .hx-entry-badge { display: flex; }
html[data-mode="mobile"] .hx-entry-card.is-undone .hx-entry-what > b { text-decoration: line-through; color: var(--color-text-muted); }
html[data-mode="mobile"] .hx-entry-card > .kv-row { min-height: 44px; padding: 8px 0; font: var(--ph-t-body); }
html[data-mode="mobile"] .hx-entry-card > .kv-row > .kv-k { font: var(--ph-t-meta); color: var(--color-text-secondary); }
html[data-mode="mobile"] .hx-entry-modal .hx-raw { margin-top: 14px; }
html[data-mode="mobile"] .hx-entry-modal .modal-footer-actions { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 8px; width: 100%; margin: 0; }
html[data-mode="mobile"] .hx-entry-modal .modal-footer .btn { justify-content: center; gap: 6px; }
html[data-mode="mobile"] .hx-entry-delete { display: flex; width: 100%; height: var(--ph-btn); margin-top: 14px; justify-content: center; gap: 6px; font-size: var(--ph-fs-body); font-weight: 600; }

/* --------------------------------------------------------------------------
   MORE AND CONNECTION (mobile-more.js, mobile-offline.js; ADR-0248, ADR-0249)
   More is a page of cards of rows; a count at a row's end is the app's own .nav-badge at the phone's size. The offline
   banner is one tappable strip under the bar on every page; the Connection page is boxed notices over the queue's rows.
   -------------------------------------------------------------------------- */
html[data-mode="mobile"] .ph-me .account-id { padding: 12px 14px; }
html[data-mode="mobile"] .ph-screen .nav-badge { flex: none; margin-left: 0; min-width: 22px; height: 22px; padding: 0 7px; background: var(--color-danger); color: var(--color-bg-elevated); font: var(--ph-t-meta); font-weight: 700; line-height: 22px; text-align: center; }

/* --------------------------------------------------------------------------
   PAGE MOTION (mobile-motion.js, ADR-0248)
   The page region is one transition group, clipped to the phone. A push slides the new page in from the right over the old
   one, which drifts left; Back runs it in reverse; a tab change cross-fades (the default). A place page's header card is
   the card it grew from: the card's box moves and resizes into it while what is inside fades across, drawn at its own
   size (never stretched) and clipped to the card. The mode scope is on the names; the `html[data-ph-nav]` rules only ever
   match while the phone's JS has a transition running.
   -------------------------------------------------------------------------- */

html[data-mode="mobile"] .main-content-body { view-transition-name: ph-page; background: var(--color-bg); }   /* opaque, so a sliding page covers the one under it */
html[data-mode="mobile"] .ph-tabbar { view-transition-name: ph-tabs; }   /* drawn above the sliding page */
html[data-mode="mobile"] .ph-place { view-transition-name: place-card; }

::view-transition-group(ph-page) { overflow: clip; animation-duration: var(--ph-t-slide); }
html[data-ph-nav="push"]::view-transition-old(ph-page) { animation: var(--ph-t-slide) var(--ph-ease) both ph-drift-out; }
html[data-ph-nav="push"]::view-transition-new(ph-page) { animation: var(--ph-t-slide) var(--ph-ease) both ph-slide-in; }
html[data-ph-nav="pop"]::view-transition-old(ph-page) { z-index: 1; animation: var(--ph-t-slide) var(--ph-ease) both ph-slide-out; }
html[data-ph-nav="pop"]::view-transition-new(ph-page) { animation: var(--ph-t-slide) var(--ph-ease) both ph-drift-in; }
html[data-ph-nav="tab"]::view-transition-old(ph-page), html[data-ph-nav="tab"]::view-transition-new(ph-page) { animation-duration: var(--ph-t-fade); }
@keyframes ph-slide-in { from { transform: translateX(100%); } }
@keyframes ph-slide-out { to { transform: translateX(100%); } }
@keyframes ph-drift-out { to { transform: translateX(-25%); opacity: .4; } }
@keyframes ph-drift-in { from { transform: translateX(-25%); opacity: .4; } }

::view-transition-group(place-card) { overflow: clip; border-radius: var(--radius-lg); animation-duration: var(--ph-t-slide); animation-timing-function: var(--ph-ease); }
::view-transition-old(place-card), ::view-transition-new(place-card) { width: 100%; height: 100%; object-fit: none; object-position: left top; }
::view-transition-old(place-card) { animation: .12s ease both ph-fade-out; }
::view-transition-new(place-card) { animation: var(--ph-t-fade) ease .06s both ph-fade-in; }
/* Opening, the list stays put and the page fades in behind the growing card; closing, the page fades off the list. */
html[data-ph-nav="morph"]::view-transition-old(ph-page) { animation: none; }
html[data-ph-nav="morph"]::view-transition-new(ph-page) { animation: var(--ph-t-fade) ease .08s both ph-fade-in; }
html[data-ph-nav="morph-back"]::view-transition-new(ph-page) { animation: none; }
html[data-ph-nav="morph-back"]::view-transition-old(ph-page) { z-index: 1; animation: var(--ph-t-fade) ease both ph-fade-out; }
@keyframes ph-fade-in { from { opacity: 0; } }
@keyframes ph-fade-out { to { opacity: 0; } }

/* A list redrawn by a change (listMotion): the page itself swaps at once and only its rows move. A row that stays slides
   to its new place, one that leaves slides off to the right and fades, one that arrives fades in. Inside a row the old and
   new look cross-fade at their own size. */
html[data-ph-nav="list"]::view-transition-old(ph-page), html[data-ph-nav="list"]::view-transition-new(ph-page) { animation: none; }
html[data-ph-nav="list"]::view-transition-old(root), html[data-ph-nav="list"]::view-transition-new(root) { animation: none; }
::view-transition-group(*.ph-row) { overflow: clip; border-radius: var(--radius-lg); animation-duration: var(--ph-t-slide); animation-timing-function: var(--ph-ease); }
::view-transition-old(*.ph-row), ::view-transition-new(*.ph-row) { height: 100%; object-fit: none; object-position: left top; }
::view-transition-old(*.ph-row):only-child { animation: var(--ph-t-slide) var(--ph-ease) both ph-row-leave; }
::view-transition-new(*.ph-row):only-child { animation: var(--ph-t-fade) ease .1s both ph-fade-in; }
@keyframes ph-row-leave { to { transform: translateX(40%); opacity: 0; } }
html[data-ph-nav="list"]::view-transition-old(place-card), html[data-ph-nav="list"]::view-transition-new(place-card) { animation: none; }

/* --------------------------------------------------------------------------
   SEARCH AND THE ACCOUNT (ADR-0248; mobile-search.js, mobile-account.js)

   A person is a ROW here, not a card: one tile whose line is the check-in button, the name with its status icons, and the
   holdings' badges at its end. A tap opens the row in place (alerts, the contact line, a line of actions). A family is a
   tinted block headed by its own card over its members' rows. The account is ONE page that grows from its row: the same
   tile at its head (the shared names below time the morph), the five sections as the bottom bar, Edit in place.

   The desk's markup stays in the tree under both: the Members card in the Search tab, the account form in the Edit tab. The
   page covers it, and the tab says so with a class the page sets while it is mounted (`is-phone-account`).
   -------------------------------------------------------------------------- */

html[data-mode="mobile"] .member-table { display: none; }

html[data-mode="mobile"] #tab-search > #search-results-content,
html[data-mode="mobile"] #tab-edit.is-phone-account > :not(.ph-account) { display: none; }
/* The desk form a phone still shows (a new account, a household) keeps its sub-tab bar, which is wider than a phone: it
   scrolls sideways there, with no scrollbar. A desktop's bar fits and keeps its own layout. */
html[data-mode="mobile"] .account-subnav { overflow-x: auto; scrollbar-width: none; }
html[data-mode="mobile"] .ph-search,
html[data-mode="mobile"] .ph-account { position: absolute; inset: 0; }

/* ---- Search: the field, the chips, the results ---------------------------------------------------------------- */
html[data-mode="mobile"] .ph-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
html[data-mode="mobile"] .ph-chips.is-wrap { margin-top: 0; }
/* Number keys on a phone: thumb-sized, the pad spaced to match. */
html[data-mode="mobile"] .chip-keys { gap: 8px; }
html[data-mode="mobile"] .chip-keys > .chip { height: var(--ph-ctl); font-size: var(--ph-fs-body); }
/* One row that scrolls sideways, so no chip is cut off: it runs to the screen's edges and its first chip lines up with the page. */
html[data-mode="mobile"] .ph-chips.is-scroll { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-inline: calc(-1 * var(--ph-inset)); padding-inline: var(--ph-inset); }
html[data-mode="mobile"] .ph-chips.is-scroll::-webkit-scrollbar { display: none; }
html[data-mode="mobile"] .ph-chips.is-scroll .chip { flex: none; }
html[data-mode="mobile"] .ph-chips .chip { height: var(--ph-ctl-s); padding: 0 12px; font-size: var(--ph-fs-meta); font-weight: 600; }

html[data-mode="mobile"] .ph-results > * + * { margin-top: var(--ph-gap); }
html[data-mode="mobile"] .ph-results > .ph-label { margin-top: 24px; }
html[data-mode="mobile"] .ph-results > .ph-label + * { margin-top: 6px; }
html[data-mode="mobile"] .ph-results.is-beside { padding: var(--ph-inset); }
html[data-mode="mobile"] .ph-label > .bi { font-size: 1rem; }
html[data-mode="mobile"] .ph-showmore { display: flex; justify-content: center; margin-top: 12px; }

/* The add-person button is a write: the viewer role never sees it (the desk's rule, kept). */
body.is-viewer .ph-search [data-action="openNewAccount"] { display: none; }

/* No account found: the app's banner and its next step, inside one card; the banner wraps its button under the title. */
html[data-mode="mobile"] .ph-noacct .search-no-account-banner { flex-wrap: wrap; }
html[data-mode="mobile"] .ph-noacct .search-no-account-title { flex: 1; min-width: 0; overflow-wrap: anywhere; }

/* ---- a person, closed and open ---------------------------------------------------------------------------------- */
html[data-mode="mobile"] .ph-tile-head { display: flex; align-items: center; gap: 12px; min-height: calc(var(--ph-row) - 20px); }
html[data-mode="mobile"] .ph-person .ph-tile-head { min-height: 0; }
html[data-mode="mobile"] .ph-person-more { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; margin-top: 10px; cursor: default; }
html[data-mode="mobile"] .ph-person-more > .ph-row-note { margin: 0; }

/* The name's line: the title, then its badges at the right. The name ellipsizes before the badges squeeze; badges that do not
   fit beside a 96px name wrap under it, right-aligned. The check-in button sits outside it, centred. */
html[data-mode="mobile"] .ph-row-title > .account-status { margin-left: 0; }   /* the flex gap spaces it; the desk margin is for inline text */
html[data-mode="mobile"] .ph-row-title > :first-child { overflow-wrap: anywhere; }   /* the name, whatever wraps it */
html[data-mode="mobile"] .ph-row-line { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px 8px; min-width: 0; }
html[data-mode="mobile"] .ph-row-line > :first-child { flex: 1 1 96px; min-width: 96px; }   /* a list row's name ends in an ellipsis before its badges leave the line (the prototype) */
html[data-mode="mobile"] .ph-row-line > .ph-row-badges { flex: 0 1 auto; justify-content: flex-end; margin: 0; }
html[data-mode="mobile"] .ph-roster-row .ph-row-title,
html[data-mode="mobile"] .ph-row-line .ph-row-title { flex-wrap: nowrap; }
html[data-mode="mobile"] .ph-roster-row .ph-row-title > *,
html[data-mode="mobile"] .ph-row-line .ph-row-title > * { flex: none; }
html[data-mode="mobile"] .ph-roster-row .ph-row-title > :first-child,
html[data-mode="mobile"] .ph-row-line .ph-row-title > :first-child { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; overflow-wrap: normal; }
html[data-mode="mobile"] .ph-row-badges.is-lead,
html[data-mode="mobile"] .ph-row-end.ph-row-badges { flex: none; margin: 0; }   /* an account section's record: its badge leads the row; a checked-in row's ends it, beside both lines */

/* A row that arrives from the enrich pass fades in; a div tile has no cells for the table's rule to reach. */
html[data-mode="mobile"] .ph-person.member-row-fadein,
html[data-mode="mobile"] .ph-family.member-row-fadein { animation: memberRowFadeIn .3s ease forwards; }
@media (prefers-reduced-motion: reduce) {
  html[data-mode="mobile"] .ph-person.member-row-fadein,
  html[data-mode="mobile"] .ph-family.member-row-fadein { animation: none; }
}

/* ---- a family: its own header card over its members' rows -------------------------------------------------------- */
html[data-mode="mobile"] .ph-family { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; padding: 10px; border-radius: var(--radius-lg); background: var(--color-bg-subtle); box-shadow: 0 0 0 1px var(--color-border-subtle); }
html[data-mode="mobile"] .ph-family-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--space-2); min-height: 52px; padding: 8px 10px 8px 14px; border-radius: var(--radius-lg); background: var(--color-bg-elevated); box-shadow: 0 0 0 1px var(--color-border-subtle); }
html[data-mode="mobile"] .ph-family-head > i { color: var(--color-text-secondary); font-size: 1.1429rem; }
html[data-mode="mobile"] .ph-family-name { flex: 1 1 96px; min-width: 96px; font: var(--ph-t-row); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html[data-mode="mobile"] .ph-family-type {
  flex: none; padding: 1px 6px; border-radius: var(--radius-sm); font-size: var(--ph-fs-label); font-weight: var(--font-bold);
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-info); background: color-mix(in srgb, var(--color-info) 14%, transparent);
}
html[data-mode="mobile"] .ph-family-badges { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px; flex: 0 1 auto; margin-left: auto; }

/* ---- the account page ------------------------------------------------------------------------------------------- */

/* Its head is the person's row, grown: the check-in button, the name with its status icons on the same line, the badges
   at its end, the status line under it. The three shared names are the desk's (v3.css #edit-account-header), so the row
   grows into this tile and back (view-morph.js). */
html[data-mode="mobile"] .ph-profile { view-transition-name: acct-card; }
html[data-mode="mobile"] .ph-profile .member-schedule-btn { view-transition-name: acct-lead; }
html[data-mode="mobile"] .ph-profile .ph-row-title > :first-child { view-transition-name: acct-name; }
html[data-mode="mobile"] .ph-profile .ph-row-line > :first-child { flex: 1 0 auto; max-width: 100%; min-width: 0; }   /* the account head's name is never squeezed for the badges: they wrap under it */
html[data-mode="mobile"] .ph-profile .ph-row-line .ph-row-title { flex-wrap: wrap; font: var(--ph-t-title); }
html[data-mode="mobile"] .ph-profile .ph-row-line .ph-row-title > :first-child { white-space: normal; overflow: visible; }
html[data-mode="mobile"] .ph-icon.is-more { font-size: 1.8571rem; }

html[data-mode="mobile"] .ph-acct-head:empty,
html[data-mode="mobile"] .ph-acct-notice:empty { display: none; }
html[data-mode="mobile"] .ph-acct-body > * + * { margin-top: var(--ph-gap); }
html[data-mode="mobile"] .ph-acct-body > .ph-label { margin-top: 24px; }
html[data-mode="mobile"] .ph-acct-body > .ph-label + * { margin-top: 6px; }
html[data-mode="mobile"] .ph-ban .ph-row-note { margin-top: 0; }
html[data-mode="mobile"] .ph-ban .ph-btn-row { margin-top: 10px; }

/* The personal card's read lines, the waiver as one sentence with its one action. */
html[data-mode="mobile"] .ph-card.is-pad > .kv-row { min-height: 44px; padding: 8px 0; }
html[data-mode="mobile"] .ph-card.is-pad > .kv-row:first-child { border-top: 0; }
html[data-mode="mobile"] .ph-waiver { display: flex; align-items: center; gap: 10px; }
html[data-mode="mobile"] .ph-waiver > i { flex: none; font-size: 1.1429rem; }
html[data-mode="mobile"] .ph-waiver.is-ok > i { color: var(--color-success); }
html[data-mode="mobile"] .ph-waiver.is-danger > i { color: var(--color-danger); }

/* Editing in place: the app's fields, unboxed in a plain stack. */
html[data-mode="mobile"] .ph-form { display: grid; gap: 10px; }
html[data-mode="mobile"] .ph-field-row { display: flex; align-items: flex-end; gap: 8px; }
html[data-mode="mobile"] .ph-field-row > .form-group { flex: 1; min-width: 0; }
html[data-mode="mobile"] .ph-form .form-input,
html[data-mode="mobile"] .ph-acct-body .form-input,
html[data-mode="mobile"] .modal-overlay.is-sheet .form-input { min-height: var(--ph-ctl); font-size: max(var(--ph-fs-body), 16px); }
html[data-mode="mobile"] .ph-btn-row { display: flex; gap: 10px; }
html[data-mode="mobile"] .ph-btn-row > .btn { flex: 1; min-width: 0; }
html[data-mode="mobile"] .ph-add { width: 100%; border-style: dashed; color: var(--color-text-secondary); justify-content: center; }
html[data-mode="mobile"] .ph-seg-full { display: flex; width: 100%; }
html[data-mode="mobile"] .ph-seg-full > .btn-toggle { flex: 1; }

/* A pass row's Remaining, right-aligned and a step up: the number over its word, at the row's end. */
html[data-mode="mobile"] .ph-remaining { flex-direction: column; align-items: flex-end; gap: 2px; }
html[data-mode="mobile"] .ph-row-end > .btn + .ph-chev { margin-left: 2px; }

/* Notes: the card, its tags, its tools (Important and Management as chips, the ⋮ at the right edge). */
html[data-mode="mobile"] .ph-note-card { display: grid; gap: 8px; }
html[data-mode="mobile"] .ph-note-card.is-muted { opacity: .7; }
html[data-mode="mobile"] .ph-note-text { font: var(--ph-t-body); overflow-wrap: anywhere; }
html[data-mode="mobile"] .ph-note-edit { min-height: 72px; resize: vertical; }
html[data-mode="mobile"] .ph-note-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font: var(--ph-t-meta); color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-note-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
html[data-mode="mobile"] .ph-note-tools > .ph-icon:last-child { margin: -4px -10px -4px auto; }   /* the record's ⋮ sits at the card's right edge */
/* A ⋮ that is an overflow menu (Follow-ups' notes) has its menu after it; it sits at the right edge the same. */
html[data-mode="mobile"] .ph-note-tools > .ph-icon.member-overflow-trigger { margin: -4px -10px -4px auto; }
html[data-mode="mobile"] .ph-note-tools .chip { height: var(--ph-ctl-s); }
html[data-mode="mobile"] .ph-fold { display: flex; align-items: center; gap: 8px; width: 100%; min-height: var(--ph-ctl); padding: 0 4px; border: 0; background: none; color: var(--color-text-muted); font: var(--ph-t-label); text-transform: uppercase; letter-spacing: .06em; }
html[data-mode="mobile"] .ph-fold > span:first-of-type { flex: 1; text-align: left; }
html[data-mode="mobile"] .ph-fold-body > * + * { margin-top: var(--ph-gap); }   /* the folded notes keep the page's rhythm */
html[data-mode="mobile"] .ph-fold-n { font: var(--ph-t-meta); text-transform: none; letter-spacing: 0; }

/* Balance: the total, the amounts, an entry opened for editing. */
html[data-mode="mobile"] .ph-total { display: flex; align-items: baseline; justify-content: space-between; padding: 14px 16px; border-radius: var(--ph-r-card); background: var(--color-bg-subtle); border: 1px solid var(--color-border); font: var(--ph-t-row); }
html[data-mode="mobile"] .ph-total b { font: var(--ph-t-num); font-variant-numeric: tabular-nums; }
html[data-mode="mobile"] .ph-total.is-owes { background: var(--color-danger-tint); border-color: color-mix(in srgb, var(--color-danger) 30%, var(--color-border)); }
html[data-mode="mobile"] .ph-total.is-owes b { color: var(--color-danger); }
html[data-mode="mobile"] .ph-total.is-credit { background: var(--color-success-tint); border-color: color-mix(in srgb, var(--color-success) 30%, var(--color-border)); }
html[data-mode="mobile"] .ph-total.is-credit b { color: var(--color-success); }
html[data-mode="mobile"] .ph-amt { flex: none; font: 650 var(--ph-fs-body)/1 var(--font-sans); font-variant-numeric: tabular-nums; }
html[data-mode="mobile"] .ph-amt.is-charge { color: var(--color-danger); }
html[data-mode="mobile"] .ph-amt.is-credit { color: var(--color-success); }
html[data-mode="mobile"] .ph-amt.is-settled { color: var(--color-text-muted); }
html[data-mode="mobile"] .ph-entry { display: grid; gap: 10px; }

/* The badge editor's sheet: the one badge drawn bigger (it is the exception to the phone's badge size), then its fields. */
html[data-mode="mobile"] .ph-badge-preview { display: grid; justify-items: center; gap: 6px; margin-bottom: 14px; text-align: center; }
html[data-mode="mobile"] .ph-badge-preview > .ph-row-badges { zoom: 1.9; margin: 4px 0 2px; }
html[data-mode="mobile"] .ph-badge-preview .pass-badge .badge-label { contain: none; }
html[data-mode="mobile"] .ph-sheet-list { display: grid; gap: var(--ph-gap); }

/* The sections as the tab bar's own place: five sections, then Edit after a rule. Which bar shows is a class of the bar. */
html[data-mode="mobile"] .ph-tabbar.is-account:has(.ph-tabbar-rule) { grid-template-columns: repeat(5, minmax(0, 1fr)) 1px minmax(0, 1fr); }
html[data-mode="mobile"] .ph-tabbar-rule { width: 1px; align-self: stretch; margin: 10px 0; background: var(--color-border); }
html[data-mode="mobile"] .ph-tab.is-edit[aria-pressed="true"] { color: var(--color-accent); }
html[data-mode="mobile"] .ph-tab.is-edit[aria-pressed="true"] .ph-tab-pill { background: var(--color-accent-tint); }

/* ============================================================================
   CAMP (ADR-0248) — the camp page, painted by mobile-camp.js into #tab-camp-checkin as that tab's presenter.
   The desk's columns hide; the page is the phone frame (bar, place header) with the day's counts and the search PINNED under
   the bar while the campers scroll. A check-in button leads each row and one ⋮ ends it. The row parts (tile, label, family,
   badges, foot) are the prototype's own and are named for what they are, not for the camp; only the strip, the pin, the
   tools and the note are the camp's.
   ============================================================================ */

html[data-mode="mobile"] #tab-camp-checkin .class-checkin-layout { display: none; }
/* A session that was ever mobile keeps nothing of the page after crossing back (detach removes it); this is the backstop. */
html[data-mode="desktop"] .ph-camp { display: none; }

/* The search rides with the counts: both stay under the bar while the campers scroll; the camp's name and day scroll away
   (the bar already names it). */
html[data-mode="mobile"] .ph-camp-pin { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
html[data-mode="mobile"] .ph-camp-find { display: flex; align-items: center; gap: 8px; }
html[data-mode="mobile"] .ph-camp-find .attendance-search, html[data-mode="mobile"] .ph-feed-find .attendance-search { flex: 1; min-width: 0; height: var(--ph-ctl); box-sizing: border-box; border-radius: var(--ph-r-ctl); }
html[data-mode="mobile"] .ph-icon.is-boxed { flex: none; border: 1px solid var(--color-border-strong); border-radius: var(--radius-sm); background: var(--color-bg-elevated); color: var(--color-text-secondary); font-size: 1.1429rem; }
html[data-mode="mobile"] .ph-icon.is-boxed::before { border-radius: var(--radius-sm); }
html[data-mode="mobile"] .ph-icon.is-boxed[aria-pressed="true"] { border-color: var(--color-accent); color: var(--color-accent); background: var(--color-accent-tint); }

/* THE DAY'S COUNTS: one quiet card, the counts on one line, number over a small label, colour only on a number that means
   something (a camper still here past pickup). It is also the list switch: a pressed count tints; nothing moves or resizes. */
html[data-mode="mobile"] .ph-camp-strip { display: grid; grid-template-columns: repeat(var(--n, 4), minmax(0, 1fr)); border-radius: var(--radius-md); background: var(--color-bg-elevated); overflow: hidden; }
html[data-mode="mobile"] .ph-camp-strip > button { position: relative; display: grid; justify-items: center; gap: 4px; min-width: 0; padding: 10px 2px; border: 0; background: none; color: var(--color-text-secondary); }
html[data-mode="mobile"] .ph-camp-strip > button + button::before { content: ''; position: absolute; left: 0; top: 24%; bottom: 24%; width: 1px; background: var(--color-border-subtle); }
html[data-mode="mobile"] .ph-camp-strip b.is-zero { color: var(--color-text-muted); }
html[data-mode="mobile"] .ph-camp-strip b.is-warn { color: var(--color-warning-ink); }
html[data-mode="mobile"] .ph-camp-strip span { max-width: 100%; font: 600 var(--ph-fs-label)/1 var(--font-sans); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html[data-mode="mobile"] .ph-camp-strip > button[aria-pressed="true"] { background: color-mix(in srgb, var(--swatch) 12%, var(--color-bg-elevated)); color: var(--color-text); }

html[data-mode="mobile"] .ph-camp-tools { display: flex; gap: 10px; }
html[data-mode="mobile"] .ph-camp-tools[hidden] { display: none; }
html[data-mode="mobile"] .ph-camp-tools .btn { flex: 1; min-width: 0; padding-inline: 10px; }

/* The closed-day and wrong-day note: a line with an icon, and the way out under it. */
html[data-mode="mobile"] .ph-camp-note { display: flex; gap: 10px; align-items: flex-start; font: var(--ph-t-body); }
html[data-mode="mobile"] .ph-camp-note > i { margin-top: 2px; font-size: 1.1429rem; color: var(--color-warning-ink); }
html[data-mode="mobile"] .ph-card.is-alert .ph-camp-note > i { color: var(--color-danger); }

/* The lists drawn into the page's holder space like the page. */
html[data-mode="mobile"] .ph-camp-list > * + * { margin-top: var(--ph-gap); }
html[data-mode="mobile"] .ph-camp-list > .ph-label + * { margin-top: 6px; }
html[data-mode="mobile"] .ph-camp-list > .ph-label:first-child { margin-top: 4px; }

/* A person's row: the button that leads it, the name and its flags, what is known of their day, one ⋮ at the end. A row
   that is gone for the day (out, no-show) reads quieter. */
html[data-mode="mobile"] .ph-tile-foot { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; margin-top: 8px; }
html[data-mode="mobile"] .ph-tile-foot > .ph-row-note { margin: 0; }
html[data-mode="mobile"] .ph-camper.is-quiet .ph-row-title { color: var(--color-text-secondary); }

/* The camper card in its sheet: the desk popover's own content (qi-*), its action rows stacked. */
html[data-mode="mobile"] .ph-camp-info .qi-contact-child { font-size: 1.1429rem; }
html[data-mode="mobile"] .ph-camp-info .qi-alerts, html[data-mode="mobile"] .ph-camp-info .qi-flags { margin-top: 10px; }
html[data-mode="mobile"] .ph-camp-info .qi-actions { margin-top: 12px; padding-top: 12px; gap: 8px; }
html[data-mode="mobile"] .ph-camp-info .qi-actions .overflow-menu-item { border: 1px solid var(--color-border); border-radius: 9px; background: var(--color-bg-elevated); }

/* ============================================================================
   SQUEEZED PAGES (ADR-0248)

   The desk's pages, squeezed onto a phone: a page that has no phone design of its own yet keeps its desk markup and has the
   phone's differences stated HERE, in one place, instead of in its own stylesheet. Each block below was a block at the
   end of a page stylesheet under `html[data-mode="mobile"]`, moved verbatim and in the stylesheets' load order (the
   phone's own rules above come first, as they did). `tests/unit/phone-css-drift.test.js` fails on a phone rule anywhere
   but this file and v3.css, so the list of what the phone changes about a page is this list.

   A page leaves the ledger when it gets a phone design: its rules are deleted here and its parts are drawn from the
   phone's parts above. Nothing in this block is a pattern to copy.
   ============================================================================ */

/* ---- from 80-groups-notifications-orders.css (1 rule) ---- */

/* The account picker window (a sheet on the phone): its two columns stack. */
html[data-mode="mobile"] .ox-grid-2 {
  grid-template-columns: minmax(0, 1fr);
}


/* ---- from 90-waivers-misc-v3-ports.css (2 rules) ---- */

/* The waiver window an account's View opens (showWaiverDetailModal): each person on two columns, the footer keeps its icons. */
html[data-mode="mobile"] .kv-row.wv-kv-people { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }


html[data-mode="mobile"] .wv-action-label { display: none; }


/* ---- from staff-training.css (6 rules) ---- */

/* ============================================================================
 * A phone: the rail folds into one line, everything is one column
 * ========================================================================== */
html[data-mode="mobile"] #tab-staff-training .tr-header .btn-label {
  display: none;
}


html[data-mode="mobile"] #tab-staff-training .tr-continue {
  flex-direction: column;
  align-items: stretch;
}


html[data-mode="mobile"] #tab-staff-training .tr-mod-end {
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}


html[data-mode="mobile"] #tab-staff-training .tr-prac {
  flex-wrap: wrap;
}


html[data-mode="mobile"] #tab-staff-training .tr-prac-actions {
  width: 100%;
  justify-content: flex-start;
}


html[data-mode="mobile"] #tab-staff-training .tr-tick {
  width: 100%;
}


/* ---- from training-team.css (10 rules) ---- */

html[data-mode="mobile"] #tab-staff-training .tr-person {
  grid-template-columns: minmax(0, 1fr) 36px;
}


html[data-mode="mobile"] #tab-staff-training .tr-person .tr-prog {
  grid-column: 1 / -1;
  grid-row: 2;
}


html[data-mode="mobile"] #tab-staff-training .tr-person .tr-status {
  grid-column: 1;
  grid-row: 3;
  flex-direction: row;
  align-items: center;
  gap: 8px;
}


html[data-mode="mobile"] #tab-staff-training .tr-person-actions {
  grid-column: 2;
  grid-row: 1;
}


html[data-mode="mobile"] #tab-staff-training .tr-pmod-count {
  margin-left: 0;
}


html[data-mode="mobile"] #tab-staff-training .tr-lesson {
  flex-wrap: wrap;
}


html[data-mode="mobile"] #tab-staff-training .tr-infobar {
  height: auto;
  flex-wrap: wrap;
  row-gap: 6px;
}


html[data-mode="mobile"] #tab-staff-training .tr-infobar .info-divider {
  display: none;
}


html[data-mode="mobile"] #tab-staff-training .tr-attn-actions .btn {
  flex: 1 1 auto;
}


html[data-mode="mobile"] #tab-staff-training #tr-q-field {
  flex: 1 1 100%;
}


/* ---- from training-reader.css (4 rules) ---- */

html[data-mode="mobile"] #tab-staff-training .tr-rail > details > summary {
  display: flex;
}


html[data-mode="mobile"] #tab-staff-training .training-detail-layout {
  grid-template-columns: 1fr;
}


html[data-mode="mobile"] #tab-staff-training .training-lesson-rail {
  position: static;
}


html[data-mode="mobile"] #tab-staff-training .training-lesson-content {
  padding: var(--space-4);
}


/* ---- from training-editor.css (1 rule) ---- */

html[data-mode="mobile"] #tab-staff-training .tr-opt {
  grid-template-columns: minmax(0, 1fr);
}


/* ---- from system-info.css (3 rules) ---- */

/* Phone: the fix button takes the width, and a row may wrap. */
html[data-mode="mobile"] .sys-attn { flex-wrap: wrap; }


html[data-mode="mobile"] .sys-attn .btn { width: 100%; min-height: 40px; }


html[data-mode="mobile"] .sys-row { flex-wrap: wrap; }



/* Stock (mobile/mobile-stock.js): the desk's markup never shows on a phone, as Follow-ups'. The view switch and the request button span the page like the account's Charge / Credit
   pair; an item's three levels under its name are design-system.css's (a choice whose end is a full-width control). */
html[data-mode="mobile"] #tab-stock > :not(#ph-stock) { display: none; }
html[data-mode="desktop"] #ph-stock { display: none; }
html[data-mode="mobile"] #ph-stock .ph-stock-ask { width: 100%; margin-top: var(--ph-gap); }
/* The row's end is two fixed slots on the row's centre line: the level tag (`.stock-level`, the desk's too); then the
   number, the point of a stock row, large and centred in a slot two figures wide (tabular), so 1 and 10 line up and a new count moves nothing. */
html[data-mode="mobile"] #ph-stock .ph-stock-amount { display: inline-flex; align-items: center; justify-content: center; width: 2ch; font: 750 var(--ph-fs-large)/1 var(--font-sans); font-variant-numeric: tabular-nums; }
html[data-mode="mobile"] #ph-stock .ph-stock-amount b { font: inherit; color: var(--color-text); }
html[data-mode="mobile"] #ph-stock .ph-stock-amount.is-none b { color: var(--color-text-muted); }
html[data-mode="mobile"] #ph-stock .ph-stock-amount.is-soon b { color: var(--color-warning-ink); }
html[data-mode="mobile"] #ph-stock .ph-stock-amount.is-low b { color: var(--color-danger); }
