/* Business Card Scanner — Minar group.
   Palette taken from the group logo: navy #01377D, emerald #23A771, teal #1D676E. */

:root {
  color-scheme: light;
  --navy: #01377d;
  --navy-700: #052f66;
  --navy-900: #021f47;
  --emerald: #23a771;
  --emerald-600: #1b8c5e;
  --teal: #1d676e;

  --bg: #f1f4f8;
  --surface: #ffffff;
  --surface-2: #f7f9fc;
  --ink: #0f1829;
  --ink-2: #3d4a60;
  --muted: #6b7890;
  --line: #dde3ec;
  --line-strong: #c3ccdb;

  --brand: var(--navy);
  --brand-ink: #ffffff;
  --ok: var(--emerald-600);
  --warn: #9a6400;
  --bad: #c0392f;

  --radius: 16px;
  --radius-sm: 10px;
  --shadow-sm: 0 1px 2px rgba(5, 23, 54, .07);
  --shadow: 0 2px 6px rgba(5, 23, 54, .06), 0 12px 28px rgba(5, 23, 54, .07);
  --focus: 0 0 0 3px rgba(35, 167, 113, .35);
}

/* The app is a light interface by design. The dark palette below is kept
   but applies only when a page opts in with <html data-theme="dark">, so a
   phone set to dark mode no longer flips the scan pages. */
:root[data-theme="dark"] {
    --bg: #0c1220;
    --surface: #151d2e;
    --surface-2: #1b2437;
    --ink: #e9eef7;
    --ink-2: #b9c4d6;
    --muted: #8793a8;
    --line: #27324a;
    --line-strong: #35425e;

    --brand: #4d8ae0;
    --brand-ink: #06101f;
    --ok: #46c489;
    --warn: #e0ad4a;
    --bad: #f0837a;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);
    --shadow: 0 2px 6px rgba(0, 0, 0, .45), 0 16px 32px rgba(0, 0, 0, .35);
}

* { box-sizing: border-box; }

/* An author `display` beats the browser's [hidden] rule, so anything the page
   hides with the attribute needs this or it stays on screen. The flip cue was
   showing from the moment the camera opened for exactly that reason. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  font: 16px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  background: var(--bg);
  color: var(--ink);
}

h1, h2, h3 { letter-spacing: -.012em; }

/* --- brand mark --------------------------------------------------------- */

.mark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: inherit;
  text-decoration: none;
}

.mark svg { flex: none; }
.mark .mark-text { display: flex; flex-direction: column; line-height: 1.15; }
.mark .mark-text small { font-size: 11px; font-weight: 600; color: var(--muted); letter-spacing: .06em; text-transform: uppercase; }

/* --- app shell ---------------------------------------------------------- */

header.bar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  padding-top: max(10px, env(safe-area-inset-top));
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--line);
}

header.bar h1 { font-size: 16px; margin: 0; flex: 1; font-weight: 650; }

header.bar a,
header.bar button.link {
  color: var(--ink-2);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  padding: 7px 11px;
  border-radius: 999px;
}

header.bar a:hover,
header.bar button.link:hover { background: var(--surface-2); color: var(--ink); }

main { max-width: 760px; margin: 0 auto; padding: 18px 16px 40px; }

/* The admin tables carry six columns and need more room than the scan page,
   which is deliberately narrow for one-handed use. */
main.wide { max-width: 1140px; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 18px;
  margin-bottom: 14px;
}

.card > h2 {
  margin: 0 0 14px;
  font-size: 15px;
  font-weight: 650;
}

/* The camera is the primary action in its step, but Submit is the primary
   action on the page, so they are deliberately different colours. */
button.wide.alt {
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-700) 100%);
  box-shadow: 0 6px 18px rgba(1, 55, 125, .22);
}

/* A numbered step heading on the scan page. */
.step { margin-bottom: 12px; }

.step .t { font-weight: 650; font-size: 15px; }
.step .t span { display: block; font-weight: 400; font-size: 13px; color: var(--muted); }

label { display: block; font-weight: 600; font-size: 14px; margin-bottom: 7px; }
.hint { color: var(--muted); font-size: 13px; font-weight: 400; }

input[type=text], input[type=password], input[type=number], select, textarea {
  width: 100%;
  padding: 13px 14px;
  font: inherit;
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  transition: border-color .15s, box-shadow .15s, background .15s;
}

input::placeholder { color: var(--muted); }

input:focus, select:focus, textarea:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--emerald);
  box-shadow: var(--focus);
}

select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 19px) 55%, calc(100% - 13px) 55%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 38px;
}

button {
  font: inherit;
  font-weight: 650;
  padding: 13px 18px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: var(--brand);
  color: var(--brand-ink);
  cursor: pointer;
  transition: filter .15s, transform .06s, background .15s;
}

button:hover:not(:disabled) { filter: brightness(1.08); }
button:active:not(:disabled) { transform: translateY(1px); }
button:focus-visible { outline: none; box-shadow: var(--focus); }
button.secondary { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
button.ghost { background: none; color: var(--brand); padding: 8px 10px; }
button:disabled { opacity: .45; cursor: not-allowed; }
button.link { background: none; border: none; cursor: pointer; padding: 0; }

button.wide {
  width: 100%;
  padding: 17px;
  font-size: 17px;
  background: linear-gradient(135deg, var(--emerald), var(--emerald-600));
  color: #fff;
  box-shadow: 0 6px 18px rgba(27, 140, 94, .28);
}

button.wide:disabled { background: var(--line-strong); color: var(--muted); box-shadow: none; }

/* --- sign in ------------------------------------------------------------ */

/* The page is the clip, with one card on it: a logo, two fields and a button.
   The brand panel, the pitch and its bullet list are gone — the clip carries
   the wordmark itself. */

.signin {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px 16px;
  max-width: none;
  margin: 0;
}

.signin-card {
  width: 100%;
  max-width: 372px;
  padding: 30px 26px 26px;
  border-radius: var(--radius);
  /* Glass, not a panel: the clip reads straight through it. .42 is as far as
     it goes and keep dark text safe — behind the card the clip runs from luma
     74 to 191, which this and the scrim land at 169-225. */
  background: rgba(255, 255, 255, .42);
  backdrop-filter: saturate(1.3) blur(26px);
  border: 1px solid rgba(255, 255, 255, .55);
  box-shadow: 0 2px 10px rgba(10, 30, 60, .12), 0 28px 70px rgba(10, 30, 60, .22);
}

.signin-logo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  margin-bottom: 24px;
  color: var(--navy);
  text-align: center;
}

.signin-logo strong { font-size: 15px; font-weight: 700; letter-spacing: .02em; }


.field { margin-bottom: 15px; }
.field-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }

.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 46px; }

.pw-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  background: none;
  border: none;
  border-radius: 50%;
  color: var(--muted);
  cursor: pointer;
}

.pw-toggle:hover { background: var(--surface-2); color: var(--ink); }
.pw-toggle:focus-visible { outline: none; box-shadow: var(--focus); }

/* The eye: the slash draws itself across when the password is showing, and
   the pupil shrinks away behind it. Both run off aria-pressed, so the button's
   state and its picture cannot disagree. The line is 21.5 units long, which is
   what the dash array has to match for it to draw rather than fade. */
.pw-toggle .eye-slash {
  stroke-dasharray: 21.5;
  stroke-dashoffset: 21.5;
  transition: stroke-dashoffset .3s ease;
}

.pw-toggle .eye-pupil,
.pw-toggle .eye-lid {
  transform-origin: 12px 12px;
  transition: transform .3s ease, opacity .25s ease;
}

.pw-toggle[aria-pressed="true"] .eye-slash { stroke-dashoffset: 0; }
.pw-toggle[aria-pressed="true"] .eye-pupil { transform: scale(.5); opacity: .5; }
/* A squint rather than a second path: the lid keeps its shape and just closes
   a little, which is what makes the two states read as one eye. */
.pw-toggle[aria-pressed="true"] .eye-lid { transform: scaleY(.74); }

/* The whole point is the movement, so for anyone who has asked for less of it
   the two states still differ — the slash is simply there or not. */
@media (prefers-reduced-motion: reduce) {
  .pw-toggle .eye-slash,
  .pw-toggle .eye-pupil,
  .pw-toggle .eye-lid { transition: none; }
}

/* --- capture tiles ------------------------------------------------------ */

/* minmax(0,1fr) so the tiles may shrink: plain 1fr keeps their content's
   width and pushes the second tile off a narrow screen. */
.shots { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

.shot {
  position: relative;
  border: 1.5px dashed var(--line-strong);
  border-radius: 14px;
  min-height: 150px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px;
  text-align: center;
  color: var(--muted);
  font-size: 14px;
  background: var(--surface-2);
  transition: border-color .15s, background .15s;
}

.shot.filled {
  border-style: solid;
  border-color: var(--emerald);
  background: color-mix(in srgb, var(--emerald) 7%, var(--surface));
  color: var(--ink);
}

.shot img { width: 100%; height: 112px; object-fit: cover; border-radius: 10px; }
.shot .actions { display: flex; gap: 6px; max-width: 100%; }
/* A half-width tile at 390px leaves about 130px for two buttons, which is
   less than their natural width — so they share the row as equal halves
   instead of wrapping and doubling the tile's height. */
.shot .actions { flex-wrap: nowrap; justify-content: center; width: 100%; }

.shot .actions button {
  flex: 1 1 0;
  min-width: 0;
  padding: 7px 4px;
  font-size: 12px;
  white-space: nowrap;
}

.shot .tag {
  position: absolute;
  top: 9px;
  left: 9px;
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px 9px;
  color: var(--muted);
}

.shot.filled .tag { border-color: var(--emerald); color: var(--emerald-600); }

.consent { display: flex; gap: 12px; align-items: flex-start; }
.consent input { width: 22px; height: 22px; margin-top: 2px; flex: none; accent-color: var(--emerald); }
.consent label { font-weight: 500; margin: 0; }

/* --- feedback ----------------------------------------------------------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%) translateY(140%);
  background: var(--navy-900);
  color: #fff;
  padding: 13px 20px;
  border-radius: 999px;
  box-shadow: var(--shadow);
  transition: transform .26s cubic-bezier(.2, .8, .3, 1);
  z-index: 50;
  max-width: 90vw;
  font-size: 14.5px;
}

.toast.show { transform: translateX(-50%) translateY(0); }
.toast.bad { background: var(--bad); }

.rows { display: flex; flex-direction: column; gap: 10px; }

/* One card per line is right on a phone and wasteful on anything else: at 760
   a row was a name on the left and a button stranded at the far right. The
   list becomes a grid of tiles instead, as many across as the width allows,
   and each tile keeps the layout it already had on the phone.
   align-items: start so a tile carrying an extra line — a reason a card needs
   attention — does not stretch its whole row to match. */
@media (min-width: 720px) {
  .rows {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(336px, 1fr));
    align-items: start;
    gap: 12px;
  }

}

.row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
}

/* Text, then the controls on a line of their own beneath it, pushed right by
   the first of them. One line across — the phone's old layout — left a real
   address and timestamp wrapping in a narrow column beside Open and the pill,
   at every width: a tile on a desktop is no wider than the phone's row was. */
.row { flex-wrap: wrap; }
.row .grow { flex: 1 0 100%; min-width: 0; }
.row > button { margin-left: auto; }
.row .grow b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .grow small { color: var(--muted); display: block; }

.pill {
  font-size: 12px;
  font-weight: 650;
  padding: 5px 11px;
  border-radius: 999px;
  white-space: nowrap;
  border: 1px solid transparent;
}

.pill.ok { background: color-mix(in srgb, var(--ok) 13%, transparent); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.pill.warn { background: color-mix(in srgb, var(--warn) 15%, transparent); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 32%, transparent); }
.pill.bad { background: color-mix(in srgb, var(--bad) 12%, transparent); color: var(--bad); border-color: color-mix(in srgb, var(--bad) 28%, transparent); }
.pill.idle { background: color-mix(in srgb, var(--muted) 13%, transparent); color: var(--muted); border-color: color-mix(in srgb, var(--muted) 26%, transparent); }

.empty { text-align: center; color: var(--muted); padding: 46px 10px; }

/* --- admin -------------------------------------------------------------- */

.tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 16px;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow-x: auto;
  scrollbar-width: none;
}

.tabs::-webkit-scrollbar { display: none; }

.tabs button {
  background: none;
  color: var(--ink-2);
  border: none;
  padding: 9px 15px;
  border-radius: 999px;
  font-size: 14px;
  white-space: nowrap;
}

.tabs button[aria-selected=true] { background: var(--brand); color: var(--brand-ink); }

table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
th { color: var(--muted); font-weight: 650; font-size: 12.5px; letter-spacing: .03em; text-transform: uppercase; }
tr:last-child td { border-bottom: none; }

dialog {
  border: none;
  border-radius: var(--radius);
  padding: 0;
  max-width: 700px;
  width: calc(100vw - 28px);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow);
}

dialog::backdrop { background: rgba(2, 16, 40, .55); backdrop-filter: blur(2px); }
dialog .body { padding: 18px; max-height: 76vh; overflow: auto; }
dialog .foot { display: flex; gap: 10px; justify-content: flex-end; padding: 13px 18px; border-top: 1px solid var(--line); background: var(--surface-2); }

.field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; }
.field-grid label { font-size: 12px; color: var(--muted); }
.lowconf input { border-color: var(--warn); background: color-mix(in srgb, var(--warn) 7%, var(--surface-2)); }
.photos { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }
.photos img { width: 100%; border-radius: 12px; border: 1px solid var(--line); }

@media (max-width: 560px) {
  .field-grid, .photos { grid-template-columns: 1fr; }
}

/* --- live scanner ------------------------------------------------------- */

.scanner {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  overscroll-behavior: contain;
}

.scanner video,
.scanner .overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.scanner .overlay { pointer-events: none; }

.scanner-top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: max(12px, env(safe-area-inset-top)) 16px 12px;
  background: linear-gradient(rgba(0, 0, 0, .7), transparent);
  color: #fff;
}

.scanner-side { flex: 1; text-align: center; font-weight: 650; font-size: 14px; }

.scanner-top button {
  background: none;
  border: none;
  color: #fff;
  font: inherit;
  font-size: 15px;
  padding: 6px 4px;
}

.scanner-torch[aria-pressed="true"] { color: #ffd45e; }

.scanner-hint {
  position: absolute;
  bottom: 152px;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  padding: 9px 18px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .62);
  color: #fff;
  font-size: 14px;
  white-space: nowrap;
}

.scanner-hint.good { background: var(--emerald-600); }

.scanner-bottom {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px 28px max(24px, env(safe-area-inset-bottom));
  background: linear-gradient(transparent, rgba(0, 0, 0, .72));
  color: #fff;
}

.scanner-shutter {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: #fff;
  border: 4px solid rgba(255, 255, 255, .45);
  background-clip: padding-box;
  padding: 0;
}

.scanner-shutter:active { transform: scale(.94); }

.scanner.flash::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #fff;
  animation: scanner-flash .25s ease-out forwards;
}

@keyframes scanner-flash {
  from { opacity: .85; }
  to { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Step dots and the skip control inside the scanner. */

.scanner-steps {
  position: absolute;
  top: calc(max(12px, env(safe-area-inset-top)) + 46px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  z-index: 2;
}

.scanner-steps .dot {
  font-size: 11.5px;
  font-weight: 650;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .6);
  background: rgba(0, 0, 0, .45);
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 999px;
  padding: 4px 12px;
}

.scanner-steps .dot.current { color: #fff; border-color: #fff; }

.scanner-steps .dot.done {
  color: #0b1f16;
  background: var(--emerald);
  border-color: var(--emerald);
}

.scanner-steps .dot.done::before { content: "✓ "; }

.scanner-skip {
  position: absolute;
  right: 24px;
  bottom: calc(max(24px, env(safe-area-inset-bottom)) + 22px);
  background: rgba(255, 255, 255, .16);
  border: 1px solid rgba(255, 255, 255, .34);
  color: #fff;
  padding: 10px 16px;
  font-size: 14px;
}

/* The flip cue between the two shots: the card turns over inside a scanner
   frame — a sweeping beam, corner brackets and a glow — so it reads as the
   machine working, the way a government ID scanner does, rather than a plain
   line of text. Everything animates transform and opacity only, so it stays
   cheap while the camera is still running. */

.flip-cue {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 30px;
  background:
    radial-gradient(420px 320px at 50% 44%, rgba(35, 167, 113, .18), transparent 70%),
    rgba(2, 10, 24, .76);
  color: #fff;
  pointer-events: none;
}

.flip-stage {
  position: relative;
  width: 240px;
  height: 160px;
  display: grid;
  place-items: center;
}

/* Soft pulse behind the card. */
.flip-cue .aura {
  position: absolute;
  width: 220px;
  height: 140px;
  border-radius: 24px;
  background: radial-gradient(closest-side, rgba(35, 167, 113, .45), transparent 75%);
  opacity: 0;
}

.flip-cue.playing .aura { animation: cue-aura 1.5s ease-out both; }

/* Four corner brackets, drawn as gradients so there are no extra elements. */
.flip-cue .brackets {
  position: absolute;
  width: 236px;
  height: 156px;
  background-image:
    linear-gradient(var(--emerald), var(--emerald)), linear-gradient(var(--emerald), var(--emerald)),
    linear-gradient(var(--emerald), var(--emerald)), linear-gradient(var(--emerald), var(--emerald)),
    linear-gradient(var(--emerald), var(--emerald)), linear-gradient(var(--emerald), var(--emerald)),
    linear-gradient(var(--emerald), var(--emerald)), linear-gradient(var(--emerald), var(--emerald));
  background-repeat: no-repeat;
  background-size: 26px 3px, 3px 26px, 26px 3px, 3px 26px,
                   26px 3px, 3px 26px, 26px 3px, 3px 26px;
  background-position:
    left top, left top,
    right top, right top,
    left bottom, left bottom,
    right bottom, right bottom;
  opacity: .9;
}

.flip-cue.playing .brackets { animation: cue-brackets 1.5s ease-out both; }

/* The scanning beam sweeps the frame twice while the card turns. */
.flip-cue .beam {
  position: absolute;
  left: 2px;
  right: 2px;
  height: 3px;
  border-radius: 3px;
  background: linear-gradient(90deg, transparent, var(--emerald) 18%, #eafff4 50%, var(--emerald) 82%, transparent);
  box-shadow: 0 0 18px rgba(35, 167, 113, .9);
  opacity: 0;
}

.flip-cue.playing .beam { animation: cue-beam 750ms ease-in-out 2 both; }

.flip-card {
  position: relative;
  width: 190px;
  height: 120px;
  transform-style: preserve-3d;
}

/* Ends a little before FLIP_PAUSE_MS in scanner.js, so the card is resting on
   its back face when the cue disappears rather than cut off mid-turn. */
.flip-cue.playing .flip-card { animation: card-flip 1.15s cubic-bezier(.45, .05, .55, .95) .1s both; }

.flip-card .face {
  position: absolute;
  inset: 0;
  border-radius: 12px;
  backface-visibility: hidden;
  background: #fff;
  box-shadow: 0 14px 34px rgba(0, 0, 0, .45), 0 0 0 1px rgba(35, 167, 113, .5);
}

/* A hint of printing on the front, so the two faces read as a card turning. */
.flip-card .face.front {
  background-image:
    linear-gradient(var(--emerald), var(--emerald)),
    linear-gradient(#c9d8ea, #c9d8ea),
    linear-gradient(#c9d8ea, #c9d8ea);
  background-repeat: no-repeat;
  background-size: 74px 9px, 100px 7px, 56px 7px;
  background-position: 22px 30px, 22px 54px, 22px 72px;
}

.flip-card .face.back {
  transform: rotateY(180deg);
  background-image: linear-gradient(#dde3ec, #dde3ec);
  background-repeat: no-repeat;
  background-size: 60px 7px;
  background-position: 22px 30px;
}

.flip-label {
  margin: 0;
  font-size: 17px;
  font-weight: 650;
  letter-spacing: .01em;
  background: linear-gradient(90deg, #ffffff 0%, #9ff0c8 35%, #ffffff 70%);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.flip-cue.playing .flip-label { animation: cue-shimmer 1.5s linear both; }

/* One continuous turn. An intermediate keyframe near 90 degrees made the card
   decelerate into the edge-on angle and accelerate out of it, which read as
   the card sticking just as it went invisible. */
@keyframes card-flip {
  from { transform: perspective(900px) rotateY(0deg); }
  to   { transform: perspective(900px) rotateY(-180deg); }
}

@keyframes cue-beam {
  0%   { transform: translateY(-74px); opacity: 0; }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { transform: translateY(74px); opacity: 0; }
}

@keyframes cue-aura {
  0%   { opacity: 0; transform: scale(.8); }
  40%  { opacity: 1; transform: scale(1.02); }
  100% { opacity: .25; transform: scale(1); }
}

@keyframes cue-brackets {
  0%   { opacity: 0; transform: scale(1.18); }
  35%  { opacity: 1; transform: scale(1); }
  100% { opacity: .85; transform: scale(1); }
}

@keyframes cue-shimmer {
  from { background-position: 120% 0; }
  to   { background-position: -40% 0; }
}

/* With reduced motion the card simply shows its back; the words still say it. */
@media (prefers-reduced-motion: reduce) {
  .flip-cue.playing .flip-card { animation: none; transform: perspective(900px) rotateY(-180deg); }
  .flip-cue.playing .beam,
  .flip-cue.playing .aura,
  .flip-cue.playing .brackets,
  .flip-cue.playing .flip-label { animation: none; opacity: 1; }
  .flip-label { color: #fff; background: none; -webkit-background-clip: border-box; background-clip: border-box; }
}

/* Admin tables on a narrow screen.
   Six columns of scan data cannot fit a phone, and squeezing them makes every
   row wrap into a tall mess. Below 720px each row becomes its own card with
   the column name beside each value. */

table.stack td.actions { white-space: nowrap; }
table.stack td[data-label="When"] { white-space: nowrap; }

/* Between the stacked layout and a comfortable table there is a band where the
   columns simply do not fit; let that scroll rather than squash. */
.scroll-x { overflow-x: auto; }

@media (max-width: 720px) {
  table.stack thead { display: none; }

  table.stack,
  table.stack tbody,
  table.stack tr,
  table.stack td { display: block; width: 100%; }

  table.stack tr {
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 10px 12px;
    margin: 10px 0;
    background: var(--surface-2);
  }

  table.stack td {
    display: flex;
    gap: 14px;
    align-items: baseline;
    justify-content: space-between;
    text-align: right;
    border: none;
    padding: 5px 0;
  }

  table.stack td::before {
    content: attr(data-label);
    flex: none;
    color: var(--muted);
    font-size: 12.5px;
    font-weight: 650;
    text-align: left;
  }

  /* The action cell has no label, so let the buttons use the full width. */
  table.stack td.actions {
    justify-content: flex-end;
    gap: 8px;
    padding-top: 10px;
    margin-top: 6px;
    border-top: 1px solid var(--line);
  }

  table.stack td.actions::before { display: none; }

  /* Long values wrap instead of pushing the row sideways. */
  table.stack td { overflow-wrap: anywhere; }

  /* A cell holding more than one line keeps them stacked: without this the
     name and the email below it become two flex items side by side. */
  table.stack td > .v { display: block; }
}

/* The footnote under the scan page: a line, not a banner. */
.event-mark {
  /* fit-content plus auto margins centres the pill without a text-align on
     the parent, which would have centred every card's text with it. */
  display: flex;
  width: fit-content;
  align-items: center;
  gap: 9px;
  margin: 26px auto 6px;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .3);
  backdrop-filter: blur(2px);
  color: #e6f0ff;
  font-size: 11px;
  letter-spacing: .07em;
}

.event-mark img { width: 15px; height: 15px; }
.event-mark b { font-weight: 700; letter-spacing: .1em; }

/* --- the signed-in pages ------------------------------------------------ */
/* Scan, My scans and Admin share the sign-in page's look: the same
   constellation still behind them, and panels of dark glass over it. Almost
   all of it is done by moving the tokens — the components already read from
   them — with a few places that had light values baked in. */

/* The dropdown's popup list is drawn by the browser, not the page, and it
   follows the colour scheme of the root element, so it is stated here rather
   than left to the phone's own setting. */
html.app-theme { color-scheme: light; }

/* Firefox paints the list from these, so they are stated as well. */
body.app-theme option {
  background-color: #ffffff;
  color: var(--ink);
}

body.app-theme {
  --bg: #eef3f7;
  --surface: rgba(255, 255, 255, .76);
  --surface-2: rgba(10, 45, 62, .055);
  --ink: #0c2733;
  --ink-2: #2f4e5d;
  --muted: #627e8c;
  --line: rgba(12, 60, 80, .14);
  --line-strong: rgba(12, 60, 80, .26);
  --brand: var(--teal);
  --brand-ink: #ffffff;
  --ok: var(--emerald-600);
  --warn: #8a5a00;
  --bad: #c0392f;
  --shadow-sm: 0 1px 2px rgba(10, 40, 60, .10);
  --shadow: 0 2px 8px rgba(10, 40, 60, .10), 0 20px 48px rgba(10, 40, 60, .14);

  color-scheme: light;
  background: var(--bg) url("/static/img/app-bg.jpg?v=2026-10-23a") center center / cover no-repeat fixed;
}

/* Once the clip is running, the poster underneath has nothing left to do. */
body.app-theme.backdrop-live { background-image: none; }

/* The clip is a bright sky, but it still carries a grey figure and darker
   crystal edges that dark text disappears into. A white wash over it keeps
   the contrast steady wherever the frame happens to be. ::after rather than
   ::before so it lands after the <video> in paint order at the same z-index;
   header and main sit above it on z-index of their own. */
body.app-theme::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom,
      rgba(255, 255, 255, .58) 0%,
      rgba(238, 245, 250, .34) 38%,
      rgba(238, 245, 250, .34) 62%,
      rgba(255, 255, 255, .60) 100%);
  transition: background .8s ease;
}

/* The bar has to out-rank main, not tie with it: both menus hang out of the
   bar and over the cards, and a card carrying backdrop-filter makes its own
   stacking context that would otherwise paint over them. A tie goes to the
   later element in the document, which is main. */
body.app-theme header.bar { position: sticky; top: 0; z-index: 40; }
body.app-theme main { position: relative; z-index: 1; }

body.app-theme header.bar {
  background: rgba(255, 255, 255, .78);
  backdrop-filter: saturate(1.2) blur(18px);
  border-bottom: 1px solid var(--line);
}

body.app-theme header.bar h1 { color: var(--ink); }
body.app-theme header.bar a:hover,
body.app-theme header.bar button.link:hover { background: rgba(10, 45, 62, .07); color: var(--ink); }

body.app-theme .card,
body.app-theme .row,
body.app-theme .tabs {
  backdrop-filter: saturate(1.15) blur(20px);
  border-color: var(--line);
}

/* Inputs: solid white so a value stays readable whatever the clip is doing
   behind it. background-color, not the shorthand — the shorthand resets the
   select arrow's size and position and the little triangle fills the whole
   control. */
body.app-theme input[type=text],
body.app-theme input[type=password],
body.app-theme input[type=number],
body.app-theme select,
body.app-theme textarea {
  background-color: rgba(255, 255, 255, .92);
  border-color: var(--line-strong);
  color: var(--ink);
}

body.app-theme input:focus,
body.app-theme select:focus,
body.app-theme textarea:focus {
  background-color: #ffffff;
  border-color: var(--emerald);
}

body.app-theme input::placeholder { color: rgba(40, 80, 100, .45); }
body.app-theme input[readonly] { color: var(--ink-2); }

/* The arrow is drawn with gradients, so it needs re-tinting and its geometry
   restating alongside. */
body.app-theme select {
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 19px) 55%, calc(100% - 13px) 55%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}


body.app-theme .shot { background: rgba(10, 45, 62, .05); }
body.app-theme .shot.filled { background: rgba(35, 167, 113, .14); }
body.app-theme .shot .tag { background: rgba(255, 255, 255, .88); color: var(--ink-2); }
body.app-theme .shot .actions button.secondary { background: rgba(10, 45, 62, .08); color: var(--ink); }

body.app-theme button.secondary { background: rgba(10, 45, 62, .08); color: var(--ink); }
body.app-theme button.wide.alt {
  background: linear-gradient(135deg, #0f7f93 0%, #084a5c 100%);
  box-shadow: 0 8px 22px rgba(3, 30, 40, .5);
}
body.app-theme button.wide:disabled { background: rgba(10, 45, 62, .10); color: var(--muted); }

body.app-theme .event-mark {
  background: rgba(255, 255, 255, .72);
  color: var(--ink-2);
}
body.app-theme .event-mark span { color: var(--emerald-600); }

/* Admin tables and the stacked rows they become on a phone. */
body.app-theme table.stack tr { background: rgba(255, 255, 255, .62); }
body.app-theme th { color: var(--muted); }

/* Dialogs sit above the glass, so they are nearly solid — reading a scan's
   fields through a moving backdrop is not a kindness. */
body.app-theme dialog {
  background: #ffffff;
  color: var(--ink);
  border: 1px solid var(--line);
}

body.app-theme dialog .foot { background: rgba(10, 45, 62, .04); }
body.app-theme .photos img { border-color: var(--line); }

/* --- following the clip ------------------------------------------------- */
/* The app clip runs from a sunlit office to a near-black room, and no single
   set of text colours survives both ends: dark type disappears into the dark
   stretch, light type into the bright one. common.js measures the frame twice
   a second and puts `backdrop-dark` on <html> and <body> while it is dark;
   everything below is the light set inverted, and nothing else changes.

   Both flags are set because the colour-scheme that decides how the browser
   paints its own <select> popup is read off the root element alone. */

html.backdrop-dark.app-theme { color-scheme: dark; }
body.app-theme.backdrop-dark option { background-color: #082029; color: var(--ink); }

/* The switch is a fade, not a cut — the clip crosses over gradually and the
   interface should read as following it rather than blinking. */
body.app-theme,
body.app-theme header.bar,
body.app-theme .card,
body.app-theme .row,
body.app-theme .tabs,
body.app-theme input,
body.app-theme select,
body.app-theme textarea,
body.app-theme .event-mark,
body.app-theme .cs-toggle,
body.app-theme .um-toggle,
body.app-theme::after {
  transition: background-color .55s ease, color .55s ease,
              border-color .55s ease, background .55s ease;
}

body.app-theme.backdrop-dark {
  --bg: #04161b;
  --surface: rgba(6, 28, 36, .62);
  --surface-2: rgba(255, 255, 255, .07);
  --ink: #e8f7fa;
  --ink-2: #bcdde4;
  --muted: #9dbfc9;
  --line: rgba(130, 220, 235, .18);
  --line-strong: rgba(130, 220, 235, .32);
  --brand: #3fd0e6;
  --brand-ink: #04101f;
  --ok: #46c489;
  --warn: #e0ad4a;
  --bad: #f0837a;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
  --shadow: 0 2px 8px rgba(0, 0, 0, .4), 0 20px 48px rgba(0, 0, 0, .34);

  color-scheme: dark;
}

/* The scrim turns over with the rest: a white wash on a dark frame would grey
   the clip out and lose exactly the contrast it is there to protect. */
body.app-theme.backdrop-dark::after {
  background:
    linear-gradient(to bottom,
      rgba(2, 14, 19, .76) 0%,
      rgba(3, 18, 24, .56) 38%,
      rgba(3, 18, 24, .56) 62%,
      rgba(2, 14, 19, .78) 100%);
}

body.app-theme.backdrop-dark header.bar { background: rgba(4, 22, 29, .74); }
body.app-theme.backdrop-dark header.bar a:hover,
body.app-theme.backdrop-dark header.bar button.link:hover {
  background: rgba(255, 255, 255, .09);
  color: #fff;
}

body.app-theme.backdrop-dark input[type=text],
body.app-theme.backdrop-dark input[type=password],
body.app-theme.backdrop-dark input[type=number],
body.app-theme.backdrop-dark select,
body.app-theme.backdrop-dark textarea {
  background-color: rgba(255, 255, 255, .10);
  border-color: var(--line-strong);
  color: var(--ink);
}

body.app-theme.backdrop-dark input:focus,
body.app-theme.backdrop-dark select:focus,
body.app-theme.backdrop-dark textarea:focus { background-color: rgba(255, 255, 255, .16); }
body.app-theme.backdrop-dark input::placeholder { color: rgba(190, 215, 225, .48); }

body.app-theme.backdrop-dark .shot { background: rgba(255, 255, 255, .06); }
body.app-theme.backdrop-dark .shot .tag { background: rgba(4, 22, 29, .82); }
body.app-theme.backdrop-dark .shot .actions button.secondary,
body.app-theme.backdrop-dark button.secondary { background: rgba(255, 255, 255, .12); color: var(--ink); }
body.app-theme.backdrop-dark button.wide:disabled { background: rgba(255, 255, 255, .10); }

body.app-theme.backdrop-dark .event-mark { background: rgba(4, 22, 29, .62); }
body.app-theme.backdrop-dark .event-mark span { color: var(--emerald); }
body.app-theme.backdrop-dark table.stack tr { background: rgba(255, 255, 255, .05); }

body.app-theme.backdrop-dark dialog { background: #06212a; }
body.app-theme.backdrop-dark dialog .foot { background: rgba(255, 255, 255, .05); }

/* The bar's two controls, and the two popups they open. */
body.app-theme.backdrop-dark .cs-toggle { background: rgba(255, 255, 255, .10); }
body.app-theme.backdrop-dark .cs-toggle:hover { background: rgba(255, 255, 255, .16); border-color: var(--brand); }
body.app-theme.backdrop-dark .cs-menu,
body.app-theme.backdrop-dark .um-menu { background: #07252f; }
body.app-theme.backdrop-dark .cs-menu li:hover,
body.app-theme.backdrop-dark .cs-menu li:focus-visible,
body.app-theme.backdrop-dark .um-menu a:hover,
body.app-theme.backdrop-dark .um-menu button:hover { background: rgba(255, 255, 255, .10); }
body.app-theme.backdrop-dark .cs-tick { color: var(--emerald); }
body.app-theme.backdrop-dark .um-toggle:hover { background: rgba(255, 255, 255, .10); }
body.app-theme.backdrop-dark .um-toggle[aria-expanded="true"] { background: rgba(255, 255, 255, .13); }

/* The navy mark is unreadable against the dark frame; the stylesheet turns it
   white rather than the page swapping the file out mid-clip. */
body.app-theme.backdrop-dark header.bar .mark img,
body.app-theme.backdrop-dark .event-mark img { filter: brightness(0) invert(1); }


/* --- sign-in over its clip --------------------------------------------- */
/* The page is the clip with one card of glass on it. A thin white wash steadies
   a backdrop that runs from navy in one corner to near-white in the other, so
   the card's dark text holds wherever the drift happens to be.
   Scoped to body.signin-page. */

/* An abstract field of particles and connecting lines, with nothing in it
   that a crop can cut through, so it simply fills the screen at every size. */
body.signin-page {
  background: #1d3f6b url("/static/img/login-bg.jpg?v=2026-10-24b") center center / cover no-repeat;
}

body.signin-page.backdrop-live { background-image: none; }

/* Above the <video>, below .signin — so it pales the clip wherever the clip
   is actually visible, and the panel's own wash still sits on top of it. */
body.signin-page::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: rgba(255, 255, 255, .20);
}

/* --- night ---------------------------------------------------------------- */
/* There is no night footage, so night reuses the golden-hour clip and simply
   turns it down. Brightness only — no saturation, contrast or tint — so it is
   the same picture, darker.

   Whatever this takes away has to come off the measurement in common.js too:
   a canvas draw reads the video's own pixels and never sees a filter, so
   without the matching DAYPARTS.dim the page would read the night clip as
   broad daylight and leave dark text on a dark screen. */

body.app-theme .bg-video { transition: filter 1.2s ease; }
html[data-daypart="night"] body.app-theme .bg-video { filter: brightness(.5); }

.bg-video {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}

body.signin-page .signin { position: relative; z-index: 1; }

/* The card sits on the clip, so its own fields are solid rather than glass:
   a value has to stay readable whatever frame is behind it. */
body.signin-page .signin-card label { color: var(--ink-2); }

body.signin-page .signin-card input {
  background: rgba(255, 255, 255, .58);
  border-color: rgba(255, 255, 255, .75);
  color: var(--ink);
}

body.signin-page .signin-card input::placeholder { color: rgba(60, 90, 120, .48); }

/* Solid on focus: a value being typed is the one thing that cannot be left
   competing with whatever is drifting past behind it. */
body.signin-page .signin-card input:focus {
  background: rgba(255, 255, 255, .95);
  border-color: var(--emerald);
  box-shadow: var(--focus);
}

body.signin-page .pw-toggle { color: var(--muted); }
body.signin-page .pw-toggle:hover { background: var(--surface-2); color: var(--ink); }


/* The counter under Submit has no surface of its own, so on a wide screen it
   landed directly on the clip and disappeared. It gets the same small pill the
   footer mark uses. */
.scan-middle .hint {
  width: fit-content;
  max-width: 100%;
  margin: 10px auto 0;
  padding: 5px 13px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .72);
  backdrop-filter: saturate(1.1) blur(10px);
}

.scan-middle .hint:empty { display: none; }

body.app-theme.backdrop-dark .scan-middle .hint { background: rgba(4, 22, 29, .62); }

/* Disabled is not invisible: the flat tint vanished against a bright frame. */
body.app-theme button.wide:disabled {
  background: rgba(255, 255, 255, .74);
  border: 1px solid var(--line-strong);
  color: var(--ink-2);
  backdrop-filter: saturate(1.1) blur(10px);
}

body.app-theme.backdrop-dark button.wide:disabled {
  background: rgba(255, 255, 255, .12);
  border-color: var(--line);
}

/* The gallery fallback under the Scan button: present, not competing. */
.upload-link {
  display: block;
  width: fit-content;
  margin: 10px auto 0;
  font-size: 13.5px;
}

/* With the tiles hidden until a side is captured, the row needs the gap
   above it only when it is actually showing something. */
.shots:not([hidden]) { margin-top: 16px; }

/* The company step is a heading and a dropdown, nothing else, so it does not
   need the full card padding or a full-height control. */
.card.compact { padding: 14px 16px; }
.card.compact .step { margin-bottom: 10px; }

select.slim { padding: 9px 12px; background-position: calc(100% - 17px) 54%, calc(100% - 11px) 54%; }

/* --- scan page layout ---------------------------------------------------- */
/* The capture card is the page: it sits in the middle of whatever height the
   screen has. The company is picked once at the start of a session and then
   left alone, so it lives in the top corner rather than taking a row of its
   own above the thing people actually use. */

.scan-layout {
  min-height: calc(100dvh - 58px);
  display: flex;
  flex-direction: column;
  padding-top: 12px;
}

.company-pick {
  align-self: flex-end;
  width: min(260px, 60%);
  margin-bottom: 10px;
}

.company-pick select { font-size: 13.5px; }

.scan-middle {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* Centred, but never pushed under the corner control on a short screen. */
  min-height: 0;
}

.scan-middle .card { margin-bottom: 14px; }

/* The capture card is a phone-shaped thing: given a desktop's width it became
   a 700px-wide Scan button, which reads as a banner rather than a control. It
   keeps a phone's measure and sits in the middle of the screen instead. */
@media (min-width: 600px) {
  .scan-middle { width: 100%; max-width: 440px; margin-inline: auto; }
}

@media (max-width: 420px) {
  .company-pick { width: 72%; }
}

/* The scan page's title is the group name, so it carries a wordmark's
   spacing rather than a sentence's. */
body.app-theme header.bar h1 { letter-spacing: .14em; font-weight: 700; }

/* --- company switcher ---------------------------------------------------- */
/* Shaped after Odoo's: a button carrying the current company, and a list
   where the active one is ticked. Built rather than a native select, which
   cannot hold the icon or the tick and whose popup the browser draws itself. */

.company-switcher { position: relative; }

.cs-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  background: rgba(255, 255, 255, .85);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 600;
  text-align: left;
}

.cs-toggle:hover { background: #ffffff; border-color: var(--teal); }
.cs-toggle:focus-visible { outline: none; box-shadow: var(--focus); }
.cs-current { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cs-caret { flex: none; opacity: .7; transition: transform .15s; }
.cs-toggle[aria-expanded="true"] .cs-caret { transform: rotate(180deg); }

.cs-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 20;
  min-width: 100%;
  max-width: 300px;
  max-height: 60vh;
  overflow-y: auto;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: #ffffff;
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  box-shadow: var(--shadow);
}

.cs-menu li {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 10px;
  border-radius: 8px;
  font-size: 13.5px;
  color: var(--ink-2);
  cursor: pointer;
  white-space: nowrap;
}

.cs-menu li:hover,
.cs-menu li:focus-visible { background: rgba(10, 45, 62, .07); outline: none; color: var(--ink); }

/* The tick holds its space whether or not it is showing, so the names line
   up in a column instead of shifting as the selection moves. */
.cs-tick { flex: none; visibility: hidden; color: var(--emerald-600); }
.cs-menu li[aria-selected="true"] { color: var(--ink); font-weight: 650; }
.cs-menu li[aria-selected="true"] .cs-tick { visibility: visible; }

/* With an Admin link present the bar runs out of room on a phone and the
   labels wrap to two lines. */
@media (max-width: 430px) {
  header.bar { gap: 2px; }
  header.bar h1 { font-size: 15px; }
  header.bar a,
  header.bar button.link { padding: 7px 7px; font-size: 13px; }
}

/* --- the top bar's controls ---------------------------------------------- */
/* The company switcher and the user chip both live in the bar, as Odoo has
   them. The chip carries what used to be loose links in the header. */

header.bar .company-switcher { margin-left: auto; max-width: 240px; }
header.bar .cs-toggle { padding: 6px 10px; font-size: 13px; }

.user-menu { position: relative; flex: none; }

.um-toggle {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 9px 5px 5px;
  background: none;
  border: 1px solid transparent;
  border-radius: 999px;
  color: var(--ink);
}

.um-toggle:hover { background: rgba(10, 45, 62, .07); }
.um-toggle[aria-expanded="true"] { background: rgba(10, 45, 62, .09); border-color: var(--line-strong); }

.um-avatar {
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, var(--emerald), var(--teal));
  color: #ffffff;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .02em;
}

.um-name { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.15; }
.um-name b { font-size: 13px; font-weight: 650; }
.um-name small { font-size: 10.5px; color: var(--muted); letter-spacing: .04em; }
.um-caret { opacity: .6; flex: none; }

.um-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 30;
  min-width: 190px;
  padding: 6px;
  background: #ffffff;
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
}

.um-menu a,
.um-menu button {
  display: block;
  width: 100%;
  padding: 9px 11px;
  border: none;
  border-radius: 8px;
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-size: 13.5px;
  font-weight: 500;
  text-align: left;
  text-decoration: none;
}

.um-menu a:hover,
.um-menu button:hover { background: rgba(10, 45, 62, .07); color: var(--ink); }
.um-menu hr { border: none; border-top: 1px solid var(--line); margin: 5px 4px; }
.um-menu #umSignOut { color: var(--bad); }

/* On a phone the bar holds a lot: the chip keeps its avatar and drops its
   name, and the switcher takes whatever is left. */
@media (max-width: 560px) {
  header.bar h1 { display: none; }
  header.bar .company-switcher { max-width: none; }
  .um-name { display: none; }
  .um-toggle { padding: 4px; }
}

#counter { text-align: center; margin: 10px 0 0; }
