/* Copyright (c) 2026 Brownie, LLC. All rights reserved. */

/*
 * The app at /app/ (app.html): the design's foundations and the shell.
 *
 * - Tokens: the colors, sizes and type from the approved design, added to
 *   the ones in styles.css. Dark mode keeps the scanner's dark colors.
 * - Components: buttons, fields, the segmented control, the switch, tags,
 *   cards, tables, arrow cells and the sync status, for pages to use as
 *   they're redesigned; and the page header, search field, filter bar,
 *   sortable table and notice card that app/team/components.ts draws.
 * - The shell: the rail on a wide screen, the four tabs on a phone (under
 *   900px wide), the bar across the top, the role switcher sheet and the
 *   team filter.
 */

/* ---------- Tokens ---------- */

:root {
  /* Lines between rows, lighter than borders. */
  --color-divider: #eef1ec;
  /* Text that's quieter than the body but stronger than muted. */
  --color-text-secondary: #3d4a42;
  /* Links and the selected item's text: a darker green for contrast. */
  --color-accent-strong: #1f6b3b;
  /* Outlined buttons and fields. */
  --color-control-border: #c9d1c5;
  --color-field: #f8faf7;
  /* The segmented control's track. */
  --color-track: #eaeee7;
  /* Text on the gold and review fills. */
  --color-ten-text: #7a5800;
  --color-ten-border: #ecd98f;
  --color-review-text: #8a4e00;
  --color-review-border: #f0cf9c;
  /* Tournament cards: blue, so practice (green) and tournament differ in
     lightness as well as hue. */
  --color-tournament: #1a5c96;
  --color-tournament-soft: #e3eef8;
  --color-neutral-soft: #eceae4;
  --color-danger-border: #e7b8b4;
  --color-scrim: rgb(22 33 27 / 42%);

  --size-control: 44px;
  --radius-card: 12px;
  --rail-width: 248px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-divider: #222c27;
    --color-text-secondary: #c3cec7;
    --color-accent-strong: #7fd29b;
    --color-control-border: #3a4740;
    --color-field: #141b17;
    --color-track: #222c27;
    --color-ten-text: #f0c03a;
    --color-ten-border: #5a4a1c;
    --color-review-text: #f2a541;
    --color-review-border: #5a4220;
    --color-tournament: #69aef0;
    --color-tournament-soft: #182a3b;
    --color-neutral-soft: #2b3630;
    --color-danger-border: #5c2b28;
    --color-scrim: rgb(0 0 0 / 60%);
  }
}

/* ---------- Components ---------- */

.button {
  min-height: var(--size-control);
}

.button.is-danger {
  border-color: var(--color-danger-border);
  color: var(--color-danger);
}

.link-button {
  display: inline-flex;
  align-items: center;
  min-height: var(--size-control);
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-accent-strong);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.link-button:hover {
  text-decoration: underline;
}

.label-caps {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.page-title {
  font-size: 2.25rem;
}

/* A choice of two or more, such as Practice or Tournament. */
.segmented {
  display: inline-flex;
  flex-wrap: wrap;
  padding: 3px;
  border-radius: 10px;
  background: var(--color-track);
}

.segment {
  display: inline-flex;
  align-items: center;
  min-height: var(--size-control);
  padding: 0 14px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--color-text-secondary);
  font: 600 0.9rem var(--font-body);
  text-decoration: none;
  cursor: pointer;
}

.segment[aria-current="page"],
.segment[aria-pressed="true"] {
  background: var(--color-surface);
  box-shadow: 0 1px 2px rgb(0 0 0 / 12%);
  color: var(--color-text);
}

/* An on-off switch: a checkbox with role="switch". */
input[type="checkbox"].switch {
  appearance: none;
  position: relative;
  width: 44px;
  height: 26px;
  margin: 0;
  border-radius: 13px;
  background: var(--color-control-border);
  cursor: pointer;
}

input[type="checkbox"].switch::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  transition: left 0.15s;
}

input[type="checkbox"].switch:checked {
  background: var(--color-accent);
}

input[type="checkbox"].switch:checked::after {
  left: 21px;
}

.tag {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--color-neutral-soft);
  color: var(--color-text-secondary);
  font-size: 0.8rem;
  font-weight: 600;
}

.tag.is-practice {
  background: var(--color-accent-soft);
  color: var(--color-accent-strong);
}

.tag.is-tournament {
  background: var(--color-tournament-soft);
  color: var(--color-tournament);
}

.tag.is-review {
  background: var(--color-review-soft);
  color: var(--color-review-text);
}

.card {
  display: grid;
  gap: 10px;
  padding: 16px 18px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-surface);
}

.card.is-review {
  border-color: var(--color-review-border);
  background: var(--color-review-soft);
}

.card-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.card-header h2 {
  font-weight: 600;
  font-size: 1.35rem;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
}

.data-table th,
.data-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--color-divider);
  text-align: left;
}

.data-table th {
  color: var(--color-text-muted);
  font-size: 0.8rem;
  font-weight: 600;
}

/* A view's parts never grow wider than the page: a wide table scrolls in its box. */
.app-content,
.app-content .team-view,
.app-content .team-view-content {
  grid-template-columns: minmax(0, 1fr);
}

/* A page's header (components.ts pageHeader): a small line, the title,
   and the page's main buttons, which go under the title on a phone. */
.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
}

.page-header-text {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.page-header .page-title {
  margin: 0;
  line-height: 1;
}

.page-header .page-title:focus:not(:focus-visible) {
  outline: none;
}

.page-eyebrow {
  color: var(--color-text-muted);
  font-size: 0.8rem;
  font-weight: 600;
}

.page-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.page-notes {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
}

.page-intro {
  max-width: 60ch;
  margin: 0;
  color: var(--color-text-secondary);
}

/* Shown only where there's no rail: under 900px wide. */
@media (min-width: 900px) {
  .phone-only {
    display: none !important;
  }
}

/* A panel opened from a page's buttons (Add archer, Edit) under its header. */
.page-panel-slot:empty {
  display: none;
}

.page-panel-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.page-panel h2:focus:not(:focus-visible) {
  outline: none;
}

.segment-count {
  color: var(--color-text-muted);
  font-weight: 500;
}

/* A search box with its magnifier (components.ts searchField). */
.search-field {
  display: flex;
  flex: 1 1 220px;
  align-items: center;
  gap: 8px;
  min-width: 0;
  min-height: var(--size-control);
  padding: 0 12px;
  border: 1px solid var(--color-control-border);
  border-radius: 8px;
  background: var(--color-field);
  color: var(--color-text-muted);
}

.search-field:focus-within {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

.search-field input {
  flex: 1;
  min-width: 0;
  min-height: calc(var(--size-control) - 2px);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--color-text);
  font: inherit;
  outline: none;
}

/* A filter's list with its label beside it (components.ts filterSelect). */
.filter-field {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--color-text-muted);
  font-size: 0.85rem;
  font-weight: 600;
}

.filter-field select,
.filter-select {
  width: auto;
  max-width: 100%;
}

/* ---------- One look for each kind of control (CODING_STANDARDS.md, "Controls") ---------- */

/* Links: one green everywhere, never the browser's blue. No specificity, so
   a component that colors its links (a tab, the rail) keeps its own. */
:where(body.app) :where(a) {
  color: var(--color-accent-strong);
  text-underline-offset: 2px;
}

/* A link drawn as a button or a segment reads as one: no underline. */
body.app a.button,
body.app a.segment {
  text-decoration: none;
}

/* Drop-down lists, form fields and the small number boxes: one field look,
   in a form, a filter bar or a table. Width stays with each layout. */
body.app select:not(.arrow-select),
body.app .form-field input:not([type="checkbox"], [type="radio"]),
body.app .tournament-box {
  min-height: var(--size-control);
  padding: 0 10px;
  border: 1px solid var(--color-control-border);
  border-radius: var(--control-radius);
  background-color: var(--color-field);
  color: var(--color-text);
  font: 500 0.95rem var(--font-body);
}

body.app select:not(.arrow-select) {
  height: var(--size-control);
}

/* A row of filters that wraps on a narrow screen. */
.filter-bar,
.filter-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}

.filter-row {
  justify-content: space-between;
}

/* A table in a card: its tools above, a note below. */
.card.table-card {
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  padding: 0;
  min-width: 0;
}

.table-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--color-divider);
}

.table-count {
  margin: 0;
  padding: 10px 16px;
  color: var(--color-text-secondary);
  font-size: 0.85rem;
  font-weight: 600;
}

.table-note {
  margin: 0;
  padding: 12px 16px;
  font-size: 0.8rem;
}

/* A sortable table (components.ts dataTable) scrolls sideways inside its
   box, so the page never does. */
.table-box {
  /* Holds the hidden headings (positioned), so they scroll with the table, not the page. */
  position: relative;
  overflow-x: auto;
  max-width: 100%;
}

.table-box .data-table th,
.table-box .data-table td {
  white-space: nowrap;
}

/* On a computer there's room for a table to fit, so its words wrap rather
   than push it wider than its box: a table that only fits scrolled sideways
   opens cut off, and focus can scroll it out of place. Headings and numbers
   stay on one line. On a phone it keeps scrolling sideways in its box. */
@media (min-width: 900px) {
  .table-box .data-table td:not(.is-numeric),
  .table-box .data-table tbody th {
    white-space: normal;
    overflow-wrap: break-word;
  }

  .table-box .data-table th,
  .table-box .data-table td {
    padding-inline: 8px;
  }
}

.table-box:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

.table-more {
  margin: 8px 16px;
}

.table-more[hidden] {
  display: none;
}

/* A few small links under a page's header: the season's other pages. */
.page-links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin: 0;
  font-size: 0.9rem;
  font-weight: 600;
}

.page-links a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  color: var(--color-accent-strong);
}

.data-table thead th {
  position: static;
  background: none;
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.data-table tbody th {
  position: static;
  background: none;
  color: var(--color-text);
  font-size: inherit;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
}

.data-table td {
  height: 48px;
  padding-block: 4px;
}

.data-table .is-numeric {
  text-align: right;
}

.data-table tbody tr.is-selected {
  background: var(--color-accent-soft);
}

.sort-button {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: var(--size-control);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
}

.sort-mark {
  font-size: 0.7rem;
}

/* A part of a page in a card under a display-font heading (components.ts
   cardSection). On a page's grid, `is-wide` cards span every column. */
.page-section {
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  min-width: 0;
}

.page-section > h2,
.page-section > h3 {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 600;
}

.page-section > h2:focus:not(:focus-visible),
.page-section > h3:focus:not(:focus-visible) {
  outline: none;
}

.page-section p {
  margin: 0;
}

/* A filter's name beside its control in a toolbar (components.ts toolbarFilter). */
.toolbar-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  min-width: 0;
}

.toolbar-filter[hidden] {
  display: none;
}

.toolbar-filter-label {
  color: var(--color-text-muted);
  font-size: 0.85rem;
  font-weight: 600;
}

/* An archer's initials in a circle beside their name (pageHeader's avatar). */
.page-header-person {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}

.page-avatar {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--color-accent-soft);
  color: var(--color-accent-strong);
  font: 700 1.5rem/1 var(--font-display);
}

@media (max-width: 600px) {
  .page-avatar {
    width: 44px;
    height: 44px;
    font-size: 1.3rem;
  }
}

/* A notice in a card (components.ts noticeCard). */
.notice-card h2 {
  margin: 0;
  font-size: 1.35rem;
}

.notice-card.is-review h2,
.notice-card.is-review p {
  color: var(--color-review-text);
}

.notice-card p {
  margin: 0;
}

/* Facts as a two-column list: "Shot  November 10, 2026". */
.fact-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 12px;
  margin: 0;
  font-size: 0.9rem;
}

.fact-list dt {
  color: var(--color-text-muted);
}

.fact-list dd {
  margin: 0;
}

.fact-list .is-strong {
  font-weight: 600;
}

.fact-list .is-review {
  color: var(--color-review-text);
  font-weight: 600;
}

/* One arrow's score. */
.arrow-cell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 48px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  background: var(--color-page);
  font: 700 1.5rem var(--font-display);
}

.arrow-cell.is-ten {
  border-color: var(--color-ten-border);
  background: var(--color-ten-soft);
  color: var(--color-ten-text);
}

.arrow-cell.is-review {
  border: 2px solid var(--color-review);
  background: var(--color-review-soft);
  color: var(--color-review-text);
}

.arrow-cell.is-blank {
  border-style: dashed;
  background: var(--color-surface);
  color: var(--color-text-muted);
}

.sync-status {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
}

.sync-status[data-kind="synced"] .line-icon {
  stroke: var(--color-accent);
}

.sync-status[data-kind="waiting"] .line-icon,
.sync-status[data-kind="attention"] .line-icon {
  stroke: var(--color-review);
}

.sync-status[data-kind="attention"] {
  color: var(--color-review-text);
}

.line-icon {
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- The shell ---------- */

body.app {
  display: grid;
  grid-template-columns: var(--rail-width) minmax(0, 1fr);
  grid-template-areas:
    "rail top"
    "rail content";
  grid-template-rows: auto 1fr;
  min-height: 100vh;
  padding: 0;
}

.app-top-bar {
  grid-area: top;
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px max(16px, env(safe-area-inset-right, 0px)) 10px
    max(16px, env(safe-area-inset-left, 0px));
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
}

.app-rail {
  grid-area: rail;
  position: sticky;
  top: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  height: 100vh;
  overflow-y: auto;
  padding: 20px 14px;
  border-right: 1px solid var(--color-border);
  background: var(--color-surface);
}

/* When the rail is taller than the screen it scrolls; nothing in it is
   squeezed. (A squeezed school switcher spilled its text out of its box.) */
.app-rail > * {
  flex-shrink: 0;
}

/* A column whose footer stays at the bottom of the window when a page is
   short, or still loading, rather than jumping up under it. */
.app-content {
  --content-top: 28px;
  --content-side: clamp(16px, 3vw, 32px);
  grid-area: content;
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-width: 0;
  padding: var(--content-top) var(--content-side) 40px;
}

/* The app bar (shell/trail.ts): a slim bar across the top of the page,
   beside the rail, holding the breadcrumb. It stretches over the page's
   padding to meet the rail and the window's edge. */
.app-crumbs {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  min-height: 48px;
  margin: calc(-1 * var(--content-top)) calc(-1 * var(--content-side)) 0;
  padding: 0 var(--content-side);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  font-size: 0.9rem;
}

.app-crumbs[hidden] {
  display: none;
}

.app-crumbs-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  margin: 0;
  padding: 0;
  list-style: none;
}

.app-crumbs-list li + li::before {
  content: "›" / "";
  margin-inline: 8px;
  color: var(--color-text-muted);
}

.app-crumbs-list a {
  font-weight: 600;
}

.app-crumbs-list [aria-current="page"] {
  color: var(--color-text-muted);
}

/* The school in the breadcrumb: text with a small caret, opening the
   school switcher's sheet. It reads as part of the trail, not a field. */
.app-crumbs-school {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}

.app-crumbs-switch {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 32px;
  margin: 0 -6px;
  padding: 0 6px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--color-text-muted);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.app-crumbs-switch.is-caret {
  justify-content: center;
  min-width: 32px;
  margin: 0;
  padding: 0;
}

.app-crumbs-switch:hover {
  background: var(--color-page);
}

/* The list that drops down under the breadcrumb's school. */
.crumb-menu {
  position: fixed;
  inset: auto;
  margin: 0;
  display: none;
  min-width: 240px;
  max-width: min(360px, calc(100vw - 16px));
  max-height: min(70vh, 520px);
  overflow-y: auto;
  padding: 6px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  color: var(--color-text);
  box-shadow: 0 8px 24px rgb(0 0 0 / 16%);
}

.crumb-menu:popover-open {
  display: grid;
  gap: 4px;
}

.crumb-menu-group {
  display: grid;
  gap: 2px;
}

.crumb-menu-group + .crumb-menu-group {
  margin-top: 4px;
  padding-top: 6px;
  border-top: 1px solid var(--color-border);
}

.crumb-menu-group > .label-caps {
  padding: 4px 10px 2px;
}

.crumb-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 6px 10px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.crumb-menu-item .place-text {
  flex: 1;
}

.crumb-menu-item:hover,
.crumb-menu-item:focus-visible {
  background: var(--color-page);
}

.crumb-menu-item[aria-current="true"] {
  background: var(--color-accent-soft);
}

.app-crumbs-back {
  display: none;
  align-items: center;
  gap: 6px;
  min-height: var(--size-control);
  font-weight: 600;
}

.app-content > .page-footer {
  margin-top: auto;
}

/* Signed out (no rail), a view and the demo banner share
   one column, as wide as a page (--page-width, styles.css) and centered, so
   a wide screen has even margins on both sides. */
.app-content > .page,
.app-content > .demo-banner {
  width: 100%;
  max-width: var(--page-width);
  margin-inline: auto;
}

/* Beside the rail (signed in), they fill the space instead, so tables,
   charts and cards use a wide screen. The setup wizard keeps its own
   narrower, centered column (.setup, app-setup.css). */
body.app:not([data-visitor="signed-out"]) .app-content > .page,
body.app:not([data-visitor="signed-out"]) .app-content > .demo-banner {
  max-width: none;
}

.app-tabs {
  display: none;
}

.app-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 6px;
  color: var(--color-text);
  font: 700 1.6rem var(--font-display);
  text-decoration: none;
}

/*
 * The mark (app/brand-mark.ts) keeps its own colors in light and dark mode.
 * Beside the wordmark it's 32px, a little taller than the wordmark's
 * capitals (Barlow Condensed at 1.6rem, so about 18px).
 */
.app-logo {
  flex: none;
}

.place-switcher {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 56px;
  padding: 8px 12px;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  background: var(--color-field);
  color: var(--color-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.place-switcher.is-static {
  cursor: default;
}

/* In the bar across a phone's top: it gives way to the brand and sync status. */
.place-switcher.is-compact {
  flex: 0 1 auto;
  min-width: 0;
  max-width: min(60vw, 280px);
  min-height: var(--size-control);
  padding: 4px 10px;
}

.place-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

/* One line each: a long school name ends in "…" (the button's title has it whole). */
.place-text > * {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.place-text .label-caps {
  font-size: 0.65rem;
  line-height: 1.3;
}

.place-text b {
  font-size: 0.95rem;
  line-height: 1.3;
}

.place-text > span:last-child {
  color: var(--color-text-muted);
  font-size: 0.8rem;
  line-height: 1.3;
}

.place-switcher .line-icon {
  flex: none;
}

.rail-list {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail-link {
  display: flex;
  align-items: center;
  min-height: var(--size-control);
  padding: 0 12px;
  border-radius: 8px;
  color: var(--color-text);
  font-weight: 500;
  text-decoration: none;
}

.rail-link:hover {
  background: var(--color-page);
}

.rail-link[aria-current="page"] {
  background: var(--color-accent-soft);
  color: var(--color-accent-strong);
  font-weight: 600;
}

.rail-group {
  display: grid;
  gap: 4px;
  padding-top: 12px;
  border-top: 1px solid var(--color-divider);
}

.rail-group > .label-caps {
  padding: 0 12px 4px;
}

.rail-footer {
  display: grid;
  gap: 4px;
  margin-top: auto;
  padding: 12px;
  border-radius: 10px;
  background: var(--color-field);
  color: var(--color-text-secondary);
  font-size: 0.85rem;
}

.rail-account {
  margin: 0;
}

.account-name {
  font-weight: 600;
}

.team-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.team-filter-label {
  color: var(--color-text-muted);
  font-weight: 600;
}

/* Signed out: just the bar with Sign in over the scanner, at every width. */
body.app[data-visitor="signed-out"] {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "top"
    "content";
}

body.app[data-visitor="signed-out"] .app-top-bar {
  display: flex;
}

body.app[data-visitor="signed-out"] .app-rail {
  display: none;
}

/* The demo banner sits over the views, not the scanner. */
.app-content > .demo-banner:has(+ main[hidden]) {
  display: none;
}

/* A phone: the bar across the top and the tabs along the bottom. */
@media (max-width: 899px) {
  body.app {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "top"
      "content"
      "tabs";
    grid-template-rows: auto 1fr auto;
  }

  .app-rail {
    display: none;
  }

  .app-top-bar {
    display: flex;
  }

  .app-top-bar .app-brand span {
    display: none;
  }

  /* Alone, with no wordmark to match, the mark keeps the old mark's size. */
  .app-top-bar .app-logo {
    width: 30px;
    height: 30px;
  }

  .app-content {
    --content-top: 16px;
    --content-side: max(16px, env(safe-area-inset-left, 0px));
    padding: var(--content-top) var(--content-side) 24px;
  }

  /* On a phone the app bar is a back arrow to the page before, under the
     top bar, rather than the whole trail. */
  .app-crumbs {
    min-height: 44px;
  }

  .app-crumbs-back {
    display: inline-flex;
  }

  .app-crumbs-list {
    display: none;
  }

  body.app:not([data-visitor="signed-out"]) .app-tabs {
    grid-area: tabs;
    position: sticky;
    bottom: 0;
    z-index: 10;
    display: flex;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    border-top: 1px solid var(--color-border);
    background: var(--color-surface);
  }

  .toast {
    bottom: calc(80px + env(safe-area-inset-bottom, 0px));
  }
}

.app-top-name {
  font-weight: 600;
}

.app-top-account {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* The sync status in the top bar, on a phone: one short line. */
.top-sync-status {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font-size: 0.8rem;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--color-text-secondary);
}

/* A photo button before the scanner's script has started. */
.button:has(+ input:disabled) {
  opacity: 0.55;
  cursor: progress;
}

.tab-link {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 56px;
  color: var(--color-text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  text-decoration: none;
}

.tab-link[aria-current="page"] {
  background: var(--color-accent-soft);
  color: var(--color-accent-strong);
}

/* ---------- The role switcher sheet ---------- */

.sheet {
  width: min(440px, 100%);
  max-height: 85vh;
  padding: 10px 20px 24px;
  border: 0;
  border-radius: 20px;
  background: var(--color-surface);
  color: var(--color-text);
}

.sheet::backdrop {
  background: var(--color-scrim);
}

@media (max-width: 899px) {
  .sheet {
    width: 100%;
    max-width: 100%;
    margin: auto 0 0;
    border-radius: 20px 20px 0 0;
    padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  }
}

.sheet-body {
  display: grid;
  gap: 16px;
}

.sheet-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.sheet-header h2 {
  font-size: 1.75rem;
}

.sheet-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--size-control);
  height: var(--size-control);
  border: 0;
  background: transparent;
  color: var(--color-text);
  cursor: pointer;
}

.sheet-group {
  display: grid;
  gap: 6px;
}

.place-choice {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 60px;
  padding: 10px 14px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.place-choice[aria-current="true"] {
  border: 2px solid var(--color-accent);
  background: var(--color-accent-soft);
}

.check-icon {
  flex: none;
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sheet-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.sheet-account {
  color: var(--color-accent-strong);
  font-weight: 600;
}

/* ---------- The feedback box (feedback-dialog.ts) ---------- */

.feedback-form {
  display: grid;
  gap: 10px;
}

.feedback-form .sheet-header h2 {
  font-size: 1.5rem;
}

.feedback-form textarea {
  width: 100%;
  min-height: 7.5rem;
  padding: 8px 10px;
  border: 1px solid var(--color-control-border);
  border-radius: var(--control-radius);
  background-color: var(--color-field);
  color: var(--color-text);
  font: 500 1rem var(--font-body);
  resize: vertical;
}

.feedback-form .field-help {
  margin: 0;
}

.feedback-photo .checkbox-label {
  margin-top: 0;
  color: var(--color-text);
  font-size: 0.95rem;
}

.feedback-problem:empty {
  display: none;
}

.feedback-form .button-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* Under the scanner's photo: "Did it read this card wrong? Report a misread". */
.report-misread {
  margin: 8px 0 0;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.report-misread[hidden] {
  display: none;
}

/* ---------- Today ---------- */

.today-waiting {
  display: flex;
  align-items: center;
  gap: 12px;
}

.today-waiting-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  color: var(--color-review-text);
}

.today-card-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.today-card-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 50px;
  border-top: 1px solid var(--color-divider);
}

.today-card-who {
  display: flex;
  flex: 1;
  flex-direction: column;
}

.today-card-total {
  font-size: 1.4rem;
}

/* The scanner's heading takes focus when moving to Scan, for screen
   readers; it needs no ring for that. */
#scan-heading:focus {
  outline: none;
}
