/* The three shaped controls (docs/design/REVIEW.md principle 1, roadmap 4): every control has the shape of its job.
   - .switch  a mode: one choice of a few, a slide switch with a travelling ink thumb (Roads, units, map motion)
   - .detents a quantity: a row of stops on a scale, the chosen one lit with a red index mark (loop length, detour)
   - .stamps  an exclusion or a tag: rubber stamps, inked when on (avoid, drive tags, spot kind)
   The state is the page's own: .on, aria-checked="true" or aria-pressed="true". Theme tokens only, so a theme restyles them. */

.switch { position: relative; display: flex; align-items: stretch; border: 2px solid var(--panel-ink); padding: 3px; gap: 0;
  background: var(--panel); min-height: 46px; }
.switch > span:not(.ctl-label) { display: none; }
.switch > button, .switch > .chip, .switch > .ink-btn { flex: 1 1 0; min-width: 0; height: auto; min-height: 38px; padding: 0 8px; border: 0;
  background: transparent; color: var(--panel-ink); font-size: 15px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background-color 0.15s ease-out, color 0.15s ease-out, box-shadow 0.15s ease-out; }
.switch > .on, .switch > [aria-checked="true"], .switch > [aria-pressed="true"] { background: var(--panel-ink); color: var(--panel);
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.35); }
.switch > button:active { box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.25); }

.detents { display: flex; flex-wrap: wrap; gap: 6px; align-items: stretch; }
.detents > span:not(.ctl-label) { display: none; }
.detents > button, .detents > .chip, .detents > .ink-btn { position: relative; flex: 1 1 0; min-width: 48px; height: auto; min-height: 44px; padding: 0 6px;
  border: 1.5px solid var(--panel-ink); background: transparent; color: var(--panel-ink); font-family: var(--font-num, inherit);
  font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.detents > button::after { content: ""; position: absolute; left: 50%; top: -1.5px; width: 2px; height: 7px; margin-left: -1px; background: var(--panel-dim); }
.detents > .on, .detents > [aria-checked="true"], .detents > [aria-pressed="true"], .detents > .busy { background: var(--panel-ink); color: var(--panel); }
.detents > .on::after, .detents > [aria-checked="true"]::after, .detents > [aria-pressed="true"]::after, .detents > .busy::after {
  background: var(--accent); height: 10px; }

.stamps { display: flex; flex-wrap: wrap; gap: 8px; }
.stamps > span:not(.ctl-label) { display: none; }
.stamps > button, .stamps > .chip, .stamps > .ink-btn { height: auto; min-height: 36px; padding: 0 12px; border: 1.5px solid var(--panel-ink);
  background: transparent; color: var(--panel-ink); font-size: 13px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  border-radius: 2px; transition: transform 0.08s ease-out, background-color 0.12s ease-out; }
.stamps > .on, .stamps > [aria-checked="true"], .stamps > [aria-pressed="true"] { background: var(--panel-ink); color: var(--panel);
  transform: rotate(-1.2deg); box-shadow: 1px 1px 0 var(--panel-dim); }
.stamps > button:active { transform: translateY(1px); }

/* a labelled control: the label above, in the type of a section head, with an optional pencil note beside it */
.ctl { margin-top: 14px; }
.ctl-label { display: flex; align-items: baseline; gap: 10px; margin: 0 0 6px; font-size: 18px; font-weight: 800; color: var(--panel-ink); }
.ctl-label small { font-size: 13px; font-weight: 500; color: var(--panel-dim); }

/* a long scale scrolls sideways (the day of a crew drive: thirty stops); a stop may carry a small word under its number */
.detents.scroll { flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; padding: 2px 0 4px; }
.detents.scroll::-webkit-scrollbar { display: none; }
.detents.scroll > button { flex: 0 0 auto; min-width: 58px; }
.detents > button b { display: block; font-weight: inherit; line-height: 1.05; }
.detents > button small { display: block; margin-top: 1px; font-family: var(--font-ui, inherit); font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }

/* The stepper: a quantity with no scale worth drawing (a time of day), stepped with two keys, the value in the numeral font. */
.stepper { display: inline-flex; align-items: stretch; min-height: 46px; border: 1.5px solid var(--panel-ink); background: var(--panel); }
.stepper > button { flex: none; width: 48px; border: 0; background: transparent; color: var(--panel-ink); font-family: var(--font-num, inherit); font-size: 24px; font-weight: 700; line-height: 1; }
.stepper > button:active { box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.25); }
.stepper > output { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; min-width: 110px; padding: 0 10px; border-left: 1.5px solid var(--panel-ink); border-right: 1.5px solid var(--panel-ink);
  font-family: var(--font-num, inherit); font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--panel-ink); }

@media (prefers-reduced-motion: reduce) {
  .switch > button, .stamps > button { transition: none; }
  .stamps > .on, .stamps > [aria-pressed="true"] { transform: none; }
}

/* The record key (principle 1; theme contract 4.3 #7): Start and Drive it are always a red key with a dot and a bevel. */
.rec-key { display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 52px; padding: 0 22px; border: 0;
  background: var(--accent); color: var(--stage); font-size: 18px; font-weight: 700; box-shadow: inset 0 -4px 0 rgba(0, 0, 0, 0.28), 0 2px 0 rgba(0, 0, 0, 0.18); }
.rec-key i { width: 12px; height: 12px; border-radius: 50%; background: currentColor; flex: none; }
.rec-key:active { box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.3); transform: translateY(1px); }
.rec-key[disabled] { opacity: 0.45; pointer-events: none; }

/* The confirm sheet (web/confirm.js): a destructive action is red text behind this sheet; Cancel is a plain key. */
.confirm-sheet { position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, 0.45); display: flex; align-items: flex-end; justify-content: center; }
.confirm-sheet .cs-box { width: 100%; max-width: 480px; background: var(--panel); color: var(--panel-ink); border-top: 2px solid var(--panel-ink);
  padding: 18px calc(16px + env(safe-area-inset-right, 0px)) calc(14px + env(safe-area-inset-bottom, 0px)) calc(16px + env(safe-area-inset-left, 0px)); }
.confirm-sheet p { margin: 0 0 14px; font-size: 16px; line-height: 1.4; }
/* TestFlight 2026-11-05 ("bad when typing"): with the keyboard up (web/keyboard.js) the sheet stands on it, its field in view */
html.kb-open .confirm-sheet { bottom: calc(100% - var(--kb-h)); }
html.kb-open .confirm-sheet .cs-box { padding-top: 12px; padding-bottom: 10px; max-height: var(--kb-h); overflow-y: auto; }
html.kb-open .confirm-sheet p { margin-bottom: 8px; } html.kb-open .confirm-sheet .cs-field { height: 44px; margin-bottom: 0; }
html.kb-open .confirm-sheet .cs-acts { margin-top: 10px; } html.kb-open .confirm-sheet .cs-acts button { min-height: 44px; }
.confirm-sheet .cs-acts { display: flex; gap: 12px; }
.confirm-sheet button { flex: 1 1 0; min-height: 52px; font: inherit; font-size: 17px; font-weight: 700; background: transparent; }
.confirm-sheet .cs-no { border: 1.5px solid var(--panel-ink); color: var(--panel-ink); box-shadow: 0 3px 0 var(--rule); }
.confirm-sheet .cs-yes { border: 0; color: var(--accent); }
.confirm-sheet .cs-ok { border: 0; color: var(--panel); background: var(--panel-ink); }   /* a name asked for (ApexConfirm.prompt): the key is plain ink */
/* a choice (ApexConfirm.choose): the options stacked, each a full-width row; the red one is the destructive one */
.confirm-sheet .cs-list label.cs-opt { display: flex; align-items: center; justify-content: center; min-height: 52px; font-size: 17px; font-weight: 700; cursor: pointer; }
/* your own photo is its own key (web/photos.js mine): a small pencil on its edge says it can be changed */
.my-photo-wrap { display: inline-flex; flex: none; }
.my-photo { position: relative; padding: 0; margin: 0; border: 0; background: none; color: inherit; border-radius: 50%; cursor: pointer; min-width: 44px; min-height: 44px; }
.my-photo-edit { position: absolute; right: -2px; bottom: -2px; width: 24px; height: 24px; border-radius: 50%; background: var(--panel-ink); color: var(--panel);
  display: grid; place-items: center; box-shadow: 0 0 0 2px var(--panel); }
.my-photo-edit svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; }
.confirm-sheet .cs-list { display: grid; gap: 8px; }
.confirm-sheet .cs-list button { flex: none; width: 100%; }
.confirm-sheet .cs-opt { border: 0; border-top: 1px solid var(--rule); color: var(--panel-ink); }
.confirm-sheet button[disabled] { opacity: 0.4; }
.confirm-sheet .cs-field { width: 100%; height: 48px; margin: 0 0 14px; padding: 0 12px; font: inherit; font-size: 17px; background: transparent; color: var(--panel-ink); border: 1.5px solid var(--panel-ink); }

/* The balance slider: a quantity with a middle (Corner mix, the dashcam's offset), a ruled track with ticks and a ring thumb.
   Never the browser's blue range. */
.balance { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 12px; min-height: 48px; font-size: 15px; font-weight: 600; }
.balance input[type=range] { -webkit-appearance: none; appearance: none; width: 100%; height: 30px; padding: 0; border: 0; background:
  linear-gradient(var(--panel-ink), var(--panel-ink)) center / 100% 2px no-repeat,
  linear-gradient(var(--panel-ink), var(--panel-ink)) 25% center / 2px 12px no-repeat, linear-gradient(var(--panel-ink), var(--panel-ink)) 50% center / 2px 12px no-repeat,
  linear-gradient(var(--panel-ink), var(--panel-ink)) 75% center / 2px 12px no-repeat; }
.balance input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 26px; height: 26px; border-radius: 50%; border: 2.5px solid var(--panel-ink); background: var(--panel); }
.balance input[type=range]::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; border: 2.5px solid var(--panel-ink); background: var(--panel); }

/* Route tuning (web/route_tuning.js): a row per slider, its name and value over the balance slider's ruled track, a hint
   under it; a slider off its default carries the accent's weight in its value. */
.tune-group h4 { margin: 14px 0 0; }
.tune-row { padding: 6px 0 2px; border-top: 1px solid var(--hair, var(--panel-dim)); }
.tune-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 15px; font-weight: 600; }
.tune-val { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--panel-dim); }
.tune-row.tuned .tune-val { color: var(--panel-ink); font-weight: 800; }
.tune-row input[type=range] { -webkit-appearance: none; appearance: none; width: 100%; height: 34px; padding: 0; border: 0; background:
  linear-gradient(var(--panel-ink), var(--panel-ink)) center / 100% 2px no-repeat; }
.tune-row input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 26px; height: 26px; border-radius: 50%; border: 2.5px solid var(--panel-ink); background: var(--panel); }
.tune-row input[type=range]::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; border: 2.5px solid var(--panel-ink); background: var(--panel); }
.tune-row input[type=range]:disabled { opacity: 0.4; }
.tune-hint { margin: 0 0 4px; }

/* A choice from a list (web/row_select.js, REVIEW2.md U-18): a row with the chosen option and a chevron, then a sheet of rows.
   The browser's <select> stays underneath, hidden, so the page reads it as before. */
.row-pick-native { display: none !important; }
.row-pick { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; min-height: 48px; padding: 0 2px;
  border: 0; border-top: 1px solid var(--hair, var(--panel-dim)); border-bottom: 1px solid var(--hair, var(--panel-dim)); background: transparent;
  color: var(--panel-ink); font: inherit; font-size: 16px; font-weight: 600; text-align: left; }
.row-pick span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-pick i { flex: none; width: 9px; height: 9px; margin-right: 6px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg) translateY(-3px); }
.row-pick[disabled] { color: var(--panel-dim); }
/* pickers one under another are one list: a single rule between them, not two with a gap (Lead and Sweep on a crew drive) */
.row-pick-list { display: grid; }
.row-pick + .row-pick-native + .row-pick { border-top: 0; }
.row-pick-sheet { position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, 0.45); display: flex; align-items: flex-end; justify-content: center; }
.row-pick-sheet .rp-box { width: 100%; max-width: 480px; max-height: 72dvh; display: flex; flex-direction: column; background: var(--panel); color: var(--panel-ink);
  border-top: 2px solid var(--panel-ink); padding: 12px calc(16px + env(safe-area-inset-right, 0px)) calc(10px + env(safe-area-inset-bottom, 0px)) calc(16px + env(safe-area-inset-left, 0px)); }
.row-pick-sheet .rp-head { margin: 0 0 6px; font-size: 13px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--panel-dim); }
.row-pick-sheet .rp-list { overflow-y: auto; overscroll-behavior: contain; }
.row-pick-sheet .rp-list button { display: block; width: 100%; min-height: 48px; padding: 0 2px 0 14px; border: 0; border-bottom: 1px solid var(--hair, var(--panel-dim));
  background: transparent; color: var(--panel-ink); font: inherit; font-size: 16px; text-align: left; position: relative; }
.row-pick-sheet .rp-list button[aria-selected="true"] { font-weight: 800; }
.row-pick-sheet .rp-list button[aria-selected="true"]::before { content: ""; position: absolute; left: 0; top: 14px; bottom: 14px; width: 3px; background: var(--accent); }
.row-pick-sheet .rp-cancel { margin-top: 8px; min-height: 48px; border: 1.5px solid var(--panel-ink); background: transparent; color: var(--panel-ink); font: inherit; font-size: 16px; font-weight: 700; }
@media (orientation: landscape) and (max-height: 540px) { .row-pick-sheet { align-items: center; } .row-pick-sheet .rp-box { max-height: 90dvh; border: 1.5px solid var(--panel-ink); } }

/* Press feedback (web/press.js makes :active fire on iOS): anything tappable dims while the finger is on it, and taps
   skip the double-tap-zoom wait. The controls above keep their own pressed look on top of this. */
button, a[href], [role="button"], [role="switch"], .sw, label, summary { touch-action: manipulation; }
button:not(:disabled):active, a[href]:active, [role="button"]:active, [role="switch"]:active, .sw:active, summary:active { opacity: 0.62; }
