/* ===========================================================================
   Banarasi Saree Authenticity Portal — component layer.

   The delivered mockups are inline-styled prototypes with no CSS classes, so
   this file is the component vocabulary they imply. Every value here comes from
   tokens.css; nothing is restyled.

   Three things the mockups specified but did not implement, authored here:
     · the <768px table-to-card collapse
     · visible focus rings (the mockups set outline:none with no replacement)
     · prefers-reduced-motion handling for the two looping animations
   =========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* The default Blazor Web App template's error banner ("Something went wrong /
   Reload"). Suppressed visually — this hides the symptom, not the underlying
   circuit/WASM error it reports, which still happens and is still worth fixing. */
#blazor-error-ui { display: none !important; }

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

body {
  margin: 0;
  background: var(--silk-2);
  color: var(--ink);
  font-family: var(--font-ui);
}

/* NOTE: `-webkit-font-smoothing: antialiased` was removed deliberately. It is a macOS
   idiom; on Windows it replaces ClearType subpixel rendering with grayscale AA, which
   renders every glyph thinner and softer — the "smooth"/washed-out look. Every platform
   now keeps its native rendering, which is markedly crisper for the thin Marcellus
   headings, the tabular figures, and Devanagari. Do not add it back globally. */

a { color: var(--oxblood); text-decoration: none; }
a:hover { color: var(--zari); }

/* Devanagari never renders in Inter or Marcellus — neither ships the glyphs.
   The mockups slip on this in six places; this class is the fix, applied at
   every Hindi run rather than to whole elements. Tiro Devanagari Hindi has a
   single 400 weight, so bold is refused outright to avoid synthetic bold. */
.deva { font-family: var(--font-deva); font-weight: 400; }

/* Focus. The mockups set outline:none on inputs and define no focus state
   anywhere else — unusable by keyboard. Every interactive element gets a ring. */
:focus-visible {
  outline: 2px solid var(--zari);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}
.on-dark :focus-visible { outline-color: var(--zari-lt); }

/* --------------------------------------------------------------------------
   Animations
   -------------------------------------------------------------------------- */
@keyframes scan     { 0% { top: 9%; } 100% { top: 87%; } }
@keyframes fadeUp   { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes sealIn   { 0% { opacity: 0; transform: scale(.5) rotate(-14deg); }
                      60% { transform: scale(1.12) rotate(5deg); }
                      100% { opacity: 1; transform: none; } }
@keyframes flagPulse{ 0%, 100% { box-shadow: 0 0 0 0 rgba(166,43,55,.45); }
                      50%      { box-shadow: 0 0 0 7px rgba(166,43,55,0); } }

/* Both looping animations are decorative. A scan line sweeping forever is a
   genuine problem for vestibular sensitivity, so it stops rather than slows. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */
.page      { max-width: 1120px; margin: 0 auto; padding: 36px 24px 80px;
             display: flex; flex-direction: column; gap: 22px; }
.page--narrow { max-width: 720px; }

.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  padding: 28px;
}

.card__head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 20px; flex-wrap: wrap; }
.card__head h2 { font: 400 22px/1 var(--font-display); margin: 0; }
.card__head .sub { font: 400 13px/1.4 var(--font-ui); color: var(--muted); }

.volunteer-create {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(280px, 360px);
  gap: 20px;
  align-items: start;
  margin: 18px 0 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}

.volunteer-create__main {
  min-width: 0;
}

.volunteer-create__grid,
.volunteer-create__uploads {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.volunteer-create__uploads {
  margin-top: 12px;
}

.volunteer-create__wide {
  grid-column: 1 / -1;
}

.volunteer-create__rail {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--silk-2);
  padding: 18px;
}

.volunteer-cluster-list {
  display: grid;
  gap: 8px;
  margin-top: 14px;
}

.volunteer-cluster-list__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper);
}

.volunteer-cluster-list__item.is-selected {
  border-color: var(--zari);
  background: rgba(201,162,39,.08);
}

.volunteer-cluster-list__code {
  font: 600 11px/1 var(--font-mono);
  color: var(--muted);
  white-space: nowrap;
}

.eyebrow {
  font: 600 11px/1 var(--font-ui);
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
}

.rule { font: 400 12px/1.5 var(--font-ui); color: var(--muted); margin: 0 0 16px; }

/* --------------------------------------------------------------------------
   StatusBadge — 8 lifecycle states plus the Flagged treatment.
   Locked and Flagged are filled/inverted; they carry the most weight and the
   design gives them the strongest presence. Cancelled adds line-through so it
   is distinguishable without relying on colour.
   -------------------------------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: 7px;
  font: 600 12px/1 var(--font-ui);
  padding: 7px 12px 7px 10px;
  border-radius: var(--r-pill);
  white-space: nowrap;
}
.badge__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }

.badge--generated,
.badge--printed   { color: var(--st-generated); background: var(--tint-generated); border: 1px solid var(--edge-generated); }
.badge--issued,
.badge--allotted  { color: var(--st-issued);    background: var(--tint-issued);    border: 1px solid var(--edge-issued); }
.badge--tagged    { color: var(--st-tagged);    background: var(--tint-tagged);    border: 1px solid var(--edge-tagged); }
.badge--returned  { color: var(--st-returned);  background: var(--tint-returned);  border: 1px solid var(--edge-returned); }
.badge--cancelled { color: var(--st-cancelled); background: var(--tint-returned);  border: 1px solid var(--edge-returned);
                    text-decoration: line-through; }
.badge--locked    { color: var(--paper); background: var(--st-locked);  border: 1px solid var(--st-locked);  font-weight: 700; }
.badge--locked .badge__dot { background: var(--zari-lt); }
.badge--flagged   { color: var(--paper); background: var(--st-flagged); border: 1px solid var(--st-flagged); font-weight: 700; }

/* The overlay pip. A flag rides on top of the lifecycle state — it never
   replaces it, so this sits over the badge rather than changing it. */
.badge-wrap { position: relative; display: inline-flex; }
.badge-flag-pip {
  position: absolute; top: -9px; right: -9px;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--st-flagged);
  display: grid; place-items: center;
  animation: flagPulse 2s infinite;
}

/* Smaller pill used inside table rows. */
.pill { display: inline-flex; align-items: center; gap: 6px;
        font: 600 11px/1 var(--font-ui); padding: 5px 9px; border-radius: var(--r-pill); }
.pill--ok     { color: var(--ok);     background: var(--tint-ok); }
.pill--danger { color: var(--danger); background: var(--tint-danger); }
.pill__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* --------------------------------------------------------------------------
   StatCard
   -------------------------------------------------------------------------- */
.stats { display: flex; flex-wrap: wrap; gap: 14px; }

.stat {
  position: relative; flex: 1; min-width: 190px;
  background: var(--silk-2); border: 1px solid var(--line);
  border-radius: 14px; padding: 18px 20px 18px 22px; overflow: hidden;
}
.stat::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0;
                width: 4px; background: var(--accent, var(--st-generated)); }
.stat__label { font: 600 11px/1 var(--font-ui); letter-spacing: .07em;
               text-transform: uppercase; color: var(--muted); }
.stat__value { font: 400 34px/1 var(--font-display); margin: 8px 0 4px; }
.stat__foot  { font: 400 12px/1 var(--font-ui); color: var(--muted); }
.stat__foot--ok     { font-weight: 600; color: var(--ok); }
.stat__foot--danger { font-weight: 600; color: var(--danger); }
.stat--danger .stat__value { color: var(--danger); }
.stat--warn   .stat__value { color: var(--warn); }

/* --------------------------------------------------------------------------
   DataTable
   -------------------------------------------------------------------------- */
.table-wrap { border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.table { width: 100%; border-collapse: collapse; font: 400 13px/1.4 var(--font-ui); }
.table thead tr { background: var(--plum); color: var(--silk); }
.table th { padding: 12px 16px; font-weight: 600; font-size: 12px; text-align: left; }
.table td { padding: 12px 16px; }
.table tbody tr { border-top: 1px solid var(--line); }
.table tbody tr:nth-child(even) { background: var(--silk-2); }
.table tbody tr.is-exception { background: rgba(166,43,55,.04); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
.table th.num { text-align: right; }
.table .primary-cell > .name { font-weight: 600; }
.table .primary-cell > .meta { color: var(--muted); font-size: 12px; }
.table .discrepancy--ok     { color: var(--ok);     font-weight: 600; }
.table .discrepancy--danger { color: var(--danger); font-weight: 700; }

/* The stated collapse. Below 768px each row becomes a card: headers move into
   ::before labels so the data keeps its meaning without a header row. */
@media (max-width: 767px) {
  .table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .table, .table tbody, .table tr, .table td { display: block; width: 100%; }
  .table-wrap { border: 0; }
  .table tbody tr {
    background: var(--silk-2) !important;
    border: 1px solid var(--line); border-left: 4px solid var(--accent, var(--st-generated));
    border-radius: 14px; padding: 14px 16px; margin-bottom: 12px;
  }
  .table tbody tr.is-exception { border-left-color: var(--danger); }
  .table td { padding: 4px 0; display: flex; justify-content: space-between; gap: 16px; }
  .table td::before {
    content: attr(data-label);
    font: 600 11px/1.4 var(--font-ui); letter-spacing: .06em;
    text-transform: uppercase; color: var(--muted);
  }
  .table td.primary-cell { display: block; margin-bottom: 8px; }
  .table td.primary-cell::before { content: none; }
  .table .num { text-align: right; }
}

/* Mobile equivalent of the desktop header checkbox (app.css:191 visually hides the
   whole <thead>, including that checkbox, since a checkbox has no text for a
   ::before label). Hidden on desktop where the real header checkbox is reachable.
   Sits inline in the toolbar row on mobile rather than as its own boxed block —
   a phone screen is tight enough that four stacked blocks (search, two buttons,
   this) pushed the actual code list below the fold for no real benefit. */
.table-select-all-mobile { display: none; }
@media (max-width: 767px) {
  .table-select-all-mobile {
    display: flex; align-items: center; gap: 8px;
    font: 600 13px/1 var(--font-ui); color: var(--ink);
  }
  .table-select-all-mobile input[type="checkbox"] { width: 20px; height: 20px; flex: none; }

  /* Tighter card padding at phone widths — 28px on a 400px screen is a fifth of
     the viewport spent on whitespace before any content starts. */
  .card { padding: 16px; }
  .table-wrap { margin-top: 10px !important; }
  .table tbody tr { padding: 10px 12px; margin-bottom: 8px; }
  .volunteer-create { grid-template-columns: 1fr; }
  .volunteer-create__grid,
  .volunteer-create__uploads {
    grid-template-columns: 1fr;
  }
  .volunteer-create__wide {
    grid-column: auto;
  }
}

/* Scoped to the batch drilldown toolbar specifically, not every .card > .row in
   the app — its row/row-of-rows gaps compound on a narrow screen where search,
   both buttons and the select-all checkbox all wrap onto their own line. */
@media (max-width: 767px) {
  .batch-toolbar-card > .row { gap: 8px; }
  .batch-toolbar-card > .row > .row { gap: 6px; }

  /* "Reprint all in batch" + "Print selected (N)" is wide text for a ~390px
     screen — a touch less horizontal padding (still a comfortable tap target)
     is what actually lets both sit on one line instead of the wider button
     wrapping alone below the other. */
  .batch-toolbar-card .btn--secondary,
  .batch-toolbar-card .btn--primary {
    padding-left: 14px;
    padding-right: 14px;
    font-size: 13px;
  }
}

/* --------------------------------------------------------------------------
   Buttons. Bordered variants use 11px vertical padding so their total height
   matches the borderless 12px ones.
   -------------------------------------------------------------------------- */
.btn {
  font: 600 14px/1 var(--font-ui);
  border-radius: var(--r-sm); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  transition: background .15s ease, filter .15s ease;
}

/* Short two-part labels ("नकली · Fake") on a decision row must stay on one line —
   wrapped mid-phrase they read as broken. Deliberately NOT applied to .btn
   globally: the weaver console's full-width Hindi buttons ("टैग करें और टाइमर
   शुरू करें") need to wrap on a narrow phone, and nowrap would overflow them.
   The row itself still wraps, so these buttons reflow — they just stay whole. */
.btn-row--compact .btn { white-space: nowrap; }
.btn:disabled { background: var(--line); color: var(--muted); cursor: not-allowed; border: none; }

.btn--primary   { border: none; background: var(--oxblood); color: var(--silk); padding: 12px 20px; }
.btn--primary:hover:not(:disabled)   { background: var(--maroon); }

.btn--gold      { border: none; background: var(--zari); color: var(--plum); padding: 12px 20px; font-weight: 700; }
.btn--gold:hover:not(:disabled)      { background: var(--zari-lt); }

.btn--secondary { border: 1.5px solid var(--oxblood); background: transparent; color: var(--oxblood); padding: 11px 20px; }
.btn--secondary:hover:not(:disabled) { background: var(--tint-oxblood); }

.btn--ghost     { border: none; background: transparent; color: var(--oxblood); padding: 12px 14px; }
.btn--ghost:hover:not(:disabled)     { background: var(--tint-oxblood); }

.btn--reject    { border: 1.5px solid var(--danger); background: transparent; color: var(--danger); padding: 11px 20px; }
.btn--reject:hover:not(:disabled)    { background: rgba(166,43,55,.08); }

/* The weaver's primary action: full width, 56px, one-handed, Hindi larger than
   the English caption because Hindi is the language of this screen. */
.btn--weaver {
  width: 100%; border: none;
  background: linear-gradient(135deg, var(--maroon), var(--oxblood));
  color: var(--silk); padding: 0 20px;
  height: var(--touch-weaver); border-radius: 14px; gap: 12px;
}
.btn--weaver:hover:not(:disabled) { filter: brightness(1.08); }
.btn--weaver .hi { font: 400 18px/1 var(--font-deva); color: var(--zari-lt); }
.btn--weaver .en { font: 600 15px/1 var(--font-ui); }

/* Any standard button placed on a weaver screen must reach the stated minimum. */
.weaver-scope .btn { min-height: var(--touch-min); }

/* --------------------------------------------------------------------------
   Inputs
   -------------------------------------------------------------------------- */
.field { display: flex; flex-direction: column; margin-bottom: 16px; }
.field__label { display: flex; align-items: center; gap: 8px;
                font: 600 12px/1 var(--font-ui); color: var(--ink); margin-bottom: 7px; }
.field__input {
  width: 100%; border: 1.5px solid var(--line); border-radius: var(--r-sm);
  padding: 12px 14px; background: var(--silk-2); color: var(--ink);
  font: 400 15px/1.2 var(--font-ui);
}
.field__input:focus { border-color: var(--zari); background: var(--paper); outline: none; }
.field__input:focus-visible { outline: 2px solid var(--zari); outline-offset: 1px; }
.field__input.deva { font-family: var(--font-deva); }
.field__input[aria-invalid="true"] {
  color: var(--danger); background: rgba(166,43,55,.04); border-color: var(--danger);
}
.field__error { font: 400 12px/1.4 var(--font-ui); color: var(--danger); margin-top: 6px; }
.field__help  { font: 400 12px/1.4 var(--font-ui); color: var(--muted); margin-top: 6px; }

/* --------------------------------------------------------------------------
   Loom-type multi-select — a weaver may work in more than one category, so the
   field holds a set of removable tags rather than one value. Built from a real
   <select> for the add step: a custom dropdown would have to reimplement
   keyboard handling and the mobile picker, and this field is used on phones.
   -------------------------------------------------------------------------- */
.loomtype-select {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  width: 100%; min-height: 48px;
  border: 1.5px solid var(--line); border-radius: var(--r-sm);
  padding: 8px 10px; background: var(--silk-2);
}
.loomtype-select:focus-within { border-color: var(--zari); background: var(--paper); }

.loomtype-tag {
  display: inline-flex; align-items: center; gap: 6px;
  font: 600 13px/1 var(--font-ui);
  color: var(--oxblood); background: var(--tint-oxblood);
  border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 7px 8px 7px 11px;
}
.loomtype-tag__x {
  border: none; background: transparent; cursor: pointer;
  color: inherit; font: 400 17px/1 var(--font-ui);
  padding: 0 2px; opacity: .65;
}
.loomtype-tag__x:hover { opacity: 1; }
.loomtype-tag__x:focus-visible { outline: 2px solid var(--zari); outline-offset: 1px; border-radius: 2px; }

/* The add picker sits inside the box and carries no border of its own, so the
   field reads as one control rather than a box with a dropdown parked in it. */
.loomtype-select__add {
  flex: 1; min-width: 150px;
  border: none; background: transparent; color: var(--muted);
  font: 400 15px/1.2 var(--font-ui);
  padding: 6px 2px; cursor: pointer;
}
.loomtype-select__add:focus { outline: none; }

.password-box {
  position: relative;
}

.password-box .field__input {
  padding-right: 142px;
}

.password-box__hint {
  position: absolute;
  right: 62px;
  top: 50%;
  transform: translateY(-50%);
  font: 600 11px/1 var(--font-ui);
  color: var(--muted);
  pointer-events: none;
  white-space: nowrap;
}

.password-box__toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  border: 0;
  background: transparent;
  color: var(--oxblood);
  padding: 8px;
  font: 700 12px/1 var(--font-ui);
  cursor: pointer;
}

.password-box__toggle:hover {
  color: var(--maroon);
}

.upload-status {
  border-radius: var(--r-pill);
  padding: 3px 7px;
  background: rgba(122,90,95,.12);
  color: var(--muted);
  font: 700 9px/1 var(--font-ui);
  letter-spacing: .07em;
  text-transform: uppercase;
}

.upload-status.is-selected {
  background: rgba(30,122,76,.12);
  color: var(--ok);
}

.upload-card {
  position: relative;
  min-height: 92px;
  border: 1.5px dashed var(--line);
  border-radius: var(--r-md);
  background: var(--silk-2);
  padding: 13px 14px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.upload-card.is-selected {
  border-style: solid;
  border-color: rgba(30,122,76,.35);
  background: rgba(30,122,76,.05);
}

.upload-card__input {
  max-width: 136px;
  font: 600 11px/1.2 var(--font-ui);
  color: var(--muted);
}

.upload-card__input::file-selector-button {
  border: 1px solid var(--oxblood);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--oxblood);
  margin-right: 8px;
  padding: 8px 10px;
  font: 700 11px/1 var(--font-ui);
  cursor: pointer;
}

.upload-card__text {
  min-width: 0;
  flex: 1;
  display: grid;
  gap: 4px;
}

.upload-card__text strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 700 12px/1.2 var(--font-ui);
}

.upload-card__text span {
  color: var(--muted);
  font: 400 11px/1.35 var(--font-ui);
}

.upload-card__remove {
  border: 0;
  background: transparent;
  color: var(--danger);
  padding: 6px 0;
  font: 700 11px/1 var(--font-ui);
  cursor: pointer;
}

.upload-card__remove:hover {
  text-decoration: underline;
}

/* PUBLIC / INTERNAL visibility chips. These are not decoration — they tell the
   person typing whether this value will ever leave the building. */
.vis { font: 600 9px/1 var(--font-ui); letter-spacing: .07em; padding: 3px 6px; border-radius: var(--r-pill); }
.vis--public   { color: var(--ok);    background: rgba(30,122,76,.12); }
.vis--internal { color: var(--muted); background: rgba(122,90,95,.14); }

/* Selectable option cards (weaver picker, volunteer picker). */
.choice {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  background: var(--paper); border: 1.5px solid var(--line);
  border-radius: var(--r-md); padding: 14px 16px; cursor: pointer; margin-bottom: 10px;
}
.choice:hover { border-color: var(--zari); }
.choice.is-selected { border: 2px solid var(--zari); background: rgba(201,162,39,.08); }
.choice__name { font-weight: 600; }
.choice__meta { color: var(--muted); font-size: 12px; }

.chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.chip {
  border: 1px solid var(--line); background: var(--paper); color: var(--ink);
  border-radius: var(--r-pill); padding: 10px 16px; cursor: pointer;
  font: 400 15px/1 var(--font-deva); min-height: var(--touch-min);
}
.chip.is-selected { background: var(--maroon); color: var(--silk); border-color: var(--maroon); }

/* --------------------------------------------------------------------------
   Role headers — each built for its person.
   -------------------------------------------------------------------------- */
.rolehead { display: flex; align-items: center; gap: 14px; color: var(--silk); }
.rolehead__avatar { border-radius: 50%; display: grid; place-items: center; flex: 0 0 auto; }

.rolehead--admin {
  background: var(--plum); border-radius: var(--r-md); padding: 12px 20px; gap: 20px;
}
.rolehead--admin .brandmark {
  width: 30px; height: 30px; border-radius: 50%; background: var(--zari);
  display: grid; place-items: center; color: var(--plum);
  font: 400 15px/1 var(--font-deva);
}
.rolehead--admin .wordmark { font: 400 15px/1.1 var(--font-display); }
.rolehead--admin nav { display: flex; gap: 4px; margin-left: 8px; flex-wrap: wrap; }
.rolehead--admin nav a { padding: 7px 12px; border-radius: var(--r-sm);
                         font: 500 12px/1 var(--font-ui); color: rgba(247,239,224,.75); }
.rolehead--admin nav a:hover { color: var(--silk); background: rgba(247,239,224,.08); }
.rolehead--admin nav a.active { font-weight: 600; background: rgba(247,239,224,.12); color: var(--paper); }

.rolehead--volunteer {
  background: var(--maroon); border-radius: var(--r-md); padding: 12px 18px; max-width: 420px;
}
.rolehead--volunteer .rolehead__avatar {
  width: 38px; height: 38px; background: var(--oxblood);
  font: 400 15px/1 var(--font-deva); color: var(--zari-lt);
}

.rolehead--weaver {
  background: linear-gradient(135deg, var(--oxblood), var(--maroon));
  border-radius: 14px; padding: 16px 18px; max-width: 420px;
}
.rolehead--weaver .rolehead__avatar {
  width: 48px; height: 48px; background: var(--zari);
  font: 400 20px/1 var(--font-deva); color: var(--plum);
}
.rolehead--weaver .greeting { font: 400 12px/1 var(--font-deva); color: var(--zari-lt); }
.rolehead--weaver .name     { font: 400 22px/1.1 var(--font-deva); margin-top: 2px; }

.rolehead--public {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  background: var(--silk); border: 1px solid var(--line); border-radius: 14px;
  padding: 20px; max-width: 420px; margin: 0 auto; color: var(--ink);
}
.rolehead--public .brandmark {
  width: 36px; height: 36px; border-radius: 50%; background: var(--plum);
  display: grid; place-items: center; color: var(--zari);
  font: 400 16px/1 var(--font-deva);
}

/* --------------------------------------------------------------------------
   CountdownTimer — the 30-minute correction window.
   -------------------------------------------------------------------------- */
.countdown { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.countdown__ring { position: relative; width: 140px; height: 140px; flex: 0 0 auto; }
.countdown__ring svg { width: 140px; height: 140px; transform: rotate(-90deg); }
.countdown__ring .track { fill: none; stroke: var(--line); stroke-width: 9; }
.countdown__ring .progress {
  fill: none; stroke-width: 9; stroke-linecap: round;
  transition: stroke-dashoffset 1s linear;
}
.countdown__centre {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.countdown__time { font: 400 30px/1 var(--font-display); font-variant-numeric: tabular-nums; }
.countdown__sub  { font: 400 11px/1 var(--font-deva); color: var(--muted); margin-top: 4px; }

/* --------------------------------------------------------------------------
   PhotoCaptureTile — live camera only.
   -------------------------------------------------------------------------- */
.capture { position: relative; width: 250px; height: 330px; border-radius: var(--r-xl); overflow: hidden; }
.capture--empty    { background: var(--plum); border: 2px dashed rgba(201,162,39,.5); }
.capture--captured { border: 2px solid var(--st-locked); }
.capture__bracket { position: absolute; width: 24px; height: 24px; }
.capture__bracket--tl { top: 14px; left: 14px;    border-left: 2px solid var(--zari-lt); border-top: 2px solid var(--zari-lt); }
.capture__bracket--tr { top: 14px; right: 14px;   border-right: 2px solid var(--zari-lt); border-top: 2px solid var(--zari-lt); }
.capture__bracket--bl { bottom: 64px; left: 14px; border-left: 2px solid var(--zari-lt); border-bottom: 2px solid var(--zari-lt); }
.capture__bracket--br { bottom: 64px; right: 14px;border-right: 2px solid var(--zari-lt); border-bottom: 2px solid var(--zari-lt); }
.capture__scanline {
  position: absolute; left: 9%; right: 9%; height: 2px;
  background: var(--zari-lt); box-shadow: 0 0 10px var(--zari);
  animation: scan 2.4s ease-in-out infinite alternate;
}
.capture__centre {
  position: absolute; top: 0; left: 0; right: 0; bottom: 64px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; color: var(--zari-lt); text-align: center; padding: 0 16px;
}
.capture__prompt   { font: 400 15px/1.3 var(--font-deva); color: var(--silk); }
.capture__prompt-en{ font: 400 11px/1.4 var(--font-ui); color: rgba(247,239,224,.6); margin-top: 6px; }

.loom-photo-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 10px 0 12px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--silk-2);
}

.loom-photo-toolbar span {
  flex: 1;
  min-width: 170px;
  color: var(--ink);
  font: 700 12px/1.3 var(--font-ui);
}

.loom-photo-toolbar .btn {
  min-height: 38px;
  padding: 9px 12px;
  font-size: 12px;
}

@media (max-width: 560px) {
  .loom-photo-toolbar {
    align-items: stretch;
  }

  .loom-photo-toolbar .btn {
    width: 100%;
  }
}

/* --------------------------------------------------------------------------
   QR auto-scan — inline preview under the weaver's code picker. Same square
   frame, corner brackets and scanline as the public /verify page's .scanner,
   so the two screens read as one visual language; unlike .capture (the
   portrait tagging-photo tile) this has no shutter button of its own, so the
   bottom brackets sit flush with the corners rather than clearing one.
   -------------------------------------------------------------------------- */
.qr-frame {
  position: relative; width: 100%; max-width: 320px; aspect-ratio: 1;
  margin: 10px auto 0; border-radius: var(--r-xl); overflow: hidden;
  background: var(--plum); border: 2px dashed rgba(201,162,39,.5);
}
.qr-frame .capture__bracket--bl { bottom: 14px; }
.qr-frame .capture__bracket--br { bottom: 14px; }
.qr-frame .capture__centre { bottom: 0; }
.qr-toggle {
  flex: 0 0 auto; width: 32px; height: 32px; display: grid; place-items: center;
  border: none; border-radius: var(--r-sm); background: transparent; color: var(--muted);
  cursor: pointer;
}
.qr-toggle:hover, .qr-toggle.is-active { background: rgba(201,162,39,.14); color: var(--zari); }
.capture__shutter {
  position: absolute; bottom: 0; left: 0; right: 0; height: 64px;
  border: none; background: var(--zari); color: var(--plum);
  font: 700 14px/1 var(--font-ui); cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 9px;
}
.capture__shutter:hover { background: var(--zari-lt); }
.capture__shutter .ring { width: 22px; height: 22px; border-radius: 50%; border: 3px solid var(--plum); }
.capture__retake {
  position: absolute; bottom: 0; left: 0; right: 0; height: var(--touch-weaver);
  border: none; background: rgba(36,6,15,.82); color: var(--silk);
  font: 600 13px/1 var(--font-ui); cursor: pointer;
}
.capture__retake:hover { background: rgba(36,6,15,.95); }
.capture__ok {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; align-items: center; gap: 6px; padding: 9px 12px;
  background: linear-gradient(var(--st-locked), transparent);
  color: var(--paper); font: 600 12px/1 var(--font-ui);
}
.capture__photo { width: 100%; height: 100%; object-fit: cover; }

.live-only {
  font: 600 11px/1 var(--font-ui); color: var(--danger);
  background: var(--tint-danger); padding: 5px 9px; border-radius: var(--r-pill);
}

/* --------------------------------------------------------------------------
   QR print label
   -------------------------------------------------------------------------- */
.label {
  width: 2in;
  height: 4in;
  max-width: 100%;
  box-sizing: border-box;
  background: var(--paper);
  border: 1.2px solid var(--ink);
  border-radius: 4px;
  overflow: hidden;
}
.label--taffeta-roll {
  display: flex;
  flex-direction: column;
}
.label__roll-panel {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: .12in;
}
.label__roll-panel--logo {
  height: 1.64in;
  gap: .02in;
}
.label__roll-panel--qr {
  height: 2.36in;
  justify-content: flex-start;
  gap: .02in;
}
.label__brand {
  align-self: stretch;
  min-height: .16in;
  color: var(--plum);
  display: grid;
  place-items: center;
  font: 700 9px/1 var(--font-ui);
  letter-spacing: .08em;
  white-space: nowrap;
}
.label__logo-full {
  width: 1.36in;
  height: 1.36in;
  object-fit: contain;
  display: block;
}
.label__organisation {
  color: var(--oxblood);
  font: 600 7px/1.15 var(--font-deva);
  text-align: center;
  white-space: nowrap;
}
.label__tagline {
  color: var(--plum);
  font: 700 7px/1.1 var(--font-ui);
  letter-spacing: .08em;
  text-transform: uppercase;
  text-align: center;
  white-space: nowrap;
}
.label__quote {
  align-self: stretch;
  color: var(--plum);
  font: 400 7px/1.12 var(--font-deva);
  text-align: center;
  overflow-wrap: anywhere;
}
.label__qr {
  width: 1.39in;
  height: 1.39in;
  flex: 0 0 auto;
  margin-top: 0;
  background: var(--paper);
  padding: 0;
}
.label__qr img,
.label__qr svg {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
}
.label__key {
  width: 100%;
  margin-top: .04in;
  font: 700 7px/1 var(--font-ui);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.label__code {
  width: 100%;
  overflow: hidden;
  text-overflow: clip;
  white-space: nowrap;
  text-align: center;
  font: 800 12px/1.1 var(--font-mono);
  letter-spacing: 0;
}
.label__batch {
  width: 100%;
  margin-top: .02in;
  overflow: hidden;
  white-space: nowrap;
  text-align: center;
  font: 700 8px/1 var(--font-mono);
}

.label-sheet { display: flex; flex-wrap: wrap; gap: .5in; }

.generated-codes {
  margin-bottom: 20px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--silk-2);
}

.generated-codes__list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.generated-codes__item {
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  font: 600 12px/1 var(--font-mono);
  color: var(--ink);
  white-space: nowrap;
}

/* On a phone the fixed-width label cards would clip against the page edge — let them
   take the full column so the whole label (QR + text) always stays visible. */
@media (max-width: 560px) {
  .label-sheet { gap: .5in; }
  .label-sheet .label { width: 2in; }
}

/* Quote Bank editor + preview: side-by-side on desktop, stacked on mobile so neither
   column is squeezed to an unreadable width. */
.quote-admin-grid {
  display: grid; grid-template-columns: 1.4fr 1fr; gap: 24px; align-items: start;
}
@media (max-width: 820px) {
  .quote-admin-grid { grid-template-columns: 1fr; gap: 18px; }
}

/* --------------------------------------------------------------------------
   EmptyState — never a grey box.
   -------------------------------------------------------------------------- */
.empty {
  position: relative; width: 100%; max-width: 340px; height: 262px;
  border-radius: var(--r-xl); overflow: hidden; border: 1px solid rgba(201,162,39,.4);
}
.empty__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(rgba(36,6,15,.35), rgba(36,6,15,.65));
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 24px; text-align: center;
}
.empty__hi { font: 400 18px/1.4 var(--font-deva); color: var(--silk); }
.empty__en { font: 400 13px/1.4 var(--font-ui); color: var(--zari-lt); font-style: italic; }

/* --------------------------------------------------------------------------
   Notices
   -------------------------------------------------------------------------- */
.notice { border-radius: var(--r-md); padding: 14px 16px; font: 400 13px/1.6 var(--font-ui); }
.notice--ok     { background: var(--tint-ok);     border: 1px solid rgba(30,122,76,.3);  color: var(--ink); }
.notice--warn   { background: rgba(154,106,0,.08);border: 1px solid rgba(154,106,0,.3);  color: var(--ink); }
.notice--danger { background: var(--tint-danger); border: 1px solid rgba(166,43,55,.3);  color: var(--ink); }
.notice--quiet  { background: transparent; border: 1px dashed var(--line); color: var(--muted); }

.admin-toast {
  position: fixed;
  top: 18px;
  right: 22px;
  z-index: 3000;
  width: min(420px, calc(100vw - 32px));
  min-height: 58px;
  padding: 14px 18px 14px 58px;
  border: 1px solid rgba(30,122,76,.28);
  border-radius: 16px;
  background: rgba(255,252,245,.98);
  color: var(--ink);
  box-shadow: 0 18px 46px rgba(36,6,15,.18), 0 4px 14px rgba(30,122,76,.12);
  animation: adminToastIn 180ms ease-out both;
}

.admin-toast::before {
  content: "✓";
  position: absolute;
  left: 16px;
  top: 50%;
  width: 28px;
  height: 28px;
  transform: translateY(-50%);
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--ok);
  color: var(--paper);
  font: 800 16px/1 var(--font-ui);
  box-shadow: 0 5px 14px rgba(30,122,76,.24);
}

.admin-toast--closing {
  animation: adminToastOut 220ms ease-in both;
}

@keyframes adminToastIn {
  from { opacity: 0; transform: translateY(-8px) scale(.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes adminToastOut {
  from { opacity: 1; transform: translateY(0) scale(1); }
  to { opacity: 0; transform: translateY(-8px) scale(.98); }
}

@media (max-width: 560px) {
  .admin-toast {
    top: 10px;
    right: 10px;
    left: 10px;
    width: auto;
    border-radius: 14px;
  }
}

/* Brand logo → home, everywhere it appears. Inherits colour so the mark is unchanged. */
.home-link { display: inline-flex; align-items: center; color: inherit; text-decoration: none; }
.home-link:hover { color: inherit; }

.mono { font-family: var(--font-mono); }
.muted { color: var(--muted); }
.stack { display: flex; flex-direction: column; gap: 12px; }
.row   { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.spacer{ flex: 1; }

/* --------------------------------------------------------------------------
   Mobile nav drawer — the native-app-style hamburger + slide-out menu shared
   by every role's shell (Admin, Volunteer server-side; Weaver's WASM console
   duplicates this markup but loads these same compiled styles). Hidden above
   900px — the same breakpoint the admin sidebar already treats as "mobile" —
   so nothing changes for desktop users of any role.
   -------------------------------------------------------------------------- */
/* The toggle checkbox is never seen — it only holds open/closed state so the whole
   drawer works with zero JS/Blazor interactivity (see MobileDrawer.razor for why). */
.drawer-toggle { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

/* ---- hamburger trigger (floating pill button) ----------------------------- */
.hamburger-btn {
  display: none;
  position: fixed; top: 14px; left: 14px; z-index: 90;
  align-items: center; justify-content: center;
  width: 46px; height: 46px; flex: 0 0 auto;
  color: var(--zari-lt);
  background:
    radial-gradient(120% 120% at 30% 20%, rgba(122,31,53,.65), transparent 60%),
    var(--plum);
  border: 1px solid rgba(240,217,138,.22);
  border-radius: 14px; cursor: pointer;
  box-shadow: 0 8px 22px rgba(15,2,5,.45), inset 0 1px 0 rgba(240,217,138,.14);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
  -webkit-tap-highlight-color: transparent;
}
.hamburger-btn:hover { border-color: rgba(240,217,138,.4); box-shadow: 0 10px 26px rgba(15,2,5,.5), inset 0 1px 0 rgba(240,217,138,.18); }
.hamburger-btn:active { transform: scale(.94); }
.hamburger-btn:focus-visible { outline: 2px solid var(--zari); outline-offset: 3px; }

/* ---- scrim ---------------------------------------------------------------- */
.drawer-scrim {
  position: fixed; inset: 0; z-index: 210;
  background: rgba(15,2,5,.62);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  cursor: pointer;
  opacity: 0; visibility: hidden;
  transition: opacity .28s ease, visibility .28s ease;
}

/* ---- panel ---------------------------------------------------------------- */
.drawer {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 220;
  width: min(86vw, 312px);
  color: var(--silk);
  /* Layered depth: a warm top glow, a maroon wash, over the deep plum base. */
  background:
    radial-gradient(140% 60% at 0% 0%, rgba(122,31,53,.55), transparent 55%),
    linear-gradient(180deg, #2B0A13 0%, var(--plum) 42%, #1B060C 100%);
  display: flex; flex-direction: column;
  transform: translateX(-100%);
  transition: transform .32s cubic-bezier(.22,.61,.36,1), box-shadow .32s ease;
  /* No shadow while closed — an off-screen panel's rightward box-shadow would still
     bleed a dark band onto the page along the left edge. Shadow appears only when open. */
  box-shadow: none;
  overflow: hidden;                    /* body scrolls, not the shell */
  border-right: 1px solid transparent;
}

/* Open state, driven purely by the hidden checkbox. */
.drawer-toggle:checked ~ .drawer {
  transform: translateX(0);
  box-shadow: 24px 0 60px rgba(15,2,5,.5);
  border-right-color: rgba(240,217,138,.1);
}
.drawer-toggle:checked ~ .drawer-scrim { opacity: 1; visibility: visible; }

/* ---- header --------------------------------------------------------------- */
.drawer__head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 20px 14px 18px 20px;
  border-bottom: 1px solid rgba(240,217,138,.12);
}
.drawer__head .admin-brand { padding: 0; gap: 12px; align-items: center; }
.drawer__head .admin-brand__logo {
  width: 42px; height: 42px; font-size: 20px;
  background: linear-gradient(145deg, var(--zari-lt), var(--zari));
  box-shadow: 0 4px 14px rgba(201,162,39,.35), inset 0 1px 0 rgba(255,255,255,.4);
}
.drawer__head .admin-brand__t1 { font: 400 19px/1.1 var(--font-deva); color: var(--silk); }
.drawer__head .admin-brand__t2 {
  font: 600 10px/1 var(--font-ui); letter-spacing: .09em; text-transform: uppercase;
  color: var(--zari-lt); opacity: .85; margin-top: 4px;
}
.drawer__close {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex: 0 0 auto;
  background: rgba(247,239,224,.06); color: rgba(247,239,224,.75);
  border: 1px solid rgba(247,239,224,.08); border-radius: 12px; cursor: pointer;
  transition: background .16s ease, color .16s ease, transform .12s ease;
  -webkit-tap-highlight-color: transparent;
}
.drawer__close:hover { background: rgba(247,239,224,.12); color: var(--silk); }
.drawer__close:active { transform: scale(.92); }
.drawer__close:focus-visible { outline: 2px solid var(--zari); outline-offset: 2px; }

/* ---- nav body ------------------------------------------------------------- */
.drawer__body {
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 2px;
  padding: 14px 12px;
  cursor: default;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; scrollbar-color: rgba(240,217,138,.25) transparent;
}
.drawer__body::-webkit-scrollbar { width: 6px; }
.drawer__body::-webkit-scrollbar-thumb { background: rgba(240,217,138,.22); border-radius: 999px; }

/* Nav links — dedicated, touch-sized treatment (NOT the dense desktop sidebar rows).
   Scoped under .drawer so the desktop .admin-nav a rules are untouched. */
.drawer .admin-nav,
.drawer__body { }
.drawer a {
  position: relative;
  display: flex; align-items: center; gap: 14px; width: 100%;
  min-height: 48px; padding: 11px 14px;
  font: 500 14.5px/1.2 var(--font-ui);
  color: rgba(247,239,224,.82); text-decoration: none;
  border-radius: 12px;
  transition: background .16s ease, color .16s ease;
  -webkit-tap-highlight-color: transparent;
}
.drawer a:hover { background: rgba(247,239,224,.07); color: var(--silk); }
.drawer a:active { background: rgba(247,239,224,.12); }
.drawer a:focus-visible { outline: 2px solid var(--zari); outline-offset: -2px; }

/* Active item — a clear gold pill plus a left accent bar (the native-app pattern). */
.drawer a.active {
  background: linear-gradient(90deg, rgba(201,162,39,.22), rgba(201,162,39,.08));
  color: var(--zari-lt); font-weight: 600;
}
.drawer a.active::before {
  content: ""; position: absolute; left: -12px; top: 50%; transform: translateY(-50%);
  width: 4px; height: 22px; border-radius: 0 4px 4px 0; background: var(--zari);
  box-shadow: 0 0 10px rgba(201,162,39,.6);
}
.drawer .admin-nav__icon { width: 20px; height: 20px; flex: 0 0 auto; opacity: .92; }
.drawer a.active .admin-nav__icon { opacity: 1; }
.drawer .admin-nav__label { flex: 1; min-width: 0; }

/* Live badges — a touch larger and brighter than the sidebar's. */
.drawer .admin-nav__badge {
  margin-left: auto; font: 700 11px/1 var(--font-ui);
  min-width: 20px; padding: 4px 8px; border-radius: 999px; color: #fff; text-align: center;
}
.drawer .admin-nav__badge--warn   { background: var(--warn); }
.drawer .admin-nav__badge--danger { background: var(--danger); box-shadow: 0 0 0 3px rgba(166,43,55,.18); }
.drawer .admin-nav__badge--super  {
  font: 700 8px/1 var(--font-ui); letter-spacing: .05em;
  background: rgba(201,162,39,.22); color: var(--zari-lt); box-shadow: inset 0 0 0 1px rgba(240,217,138,.35);
}

/* Section divider ("SETTINGS") — hairline + spaced label. */
.drawer .admin-nav__group {
  font: 700 10px/1 var(--font-ui); letter-spacing: .14em; text-transform: uppercase;
  color: rgba(247,239,224,.4);
  margin: 14px 6px 6px; padding: 14px 8px 0;
  border-top: 1px solid rgba(247,239,224,.1);
}

/* ---- footer identity + logout --------------------------------------------- */
.drawer .admin-side-foot {
  margin: 4px 12px 10px; padding: 12px;
  display: flex; align-items: center; gap: 12px;
  background: rgba(247,239,224,.05);
  border: 1px solid rgba(240,217,138,.12); border-radius: 14px;
  border-top: 1px solid rgba(240,217,138,.12);   /* override the sidebar's top-only rule */
}
.drawer .admin-side-foot__avatar {
  width: 40px; height: 40px; font-size: 14px;
  background: linear-gradient(145deg, var(--maroon), var(--oxblood));
  box-shadow: inset 0 0 0 2px rgba(240,217,138,.35), 0 3px 10px rgba(15,2,5,.4);
}
.drawer .admin-side-foot__name { font: 600 14px/1.2 var(--font-ui); color: var(--silk); }
.drawer .admin-side-foot__role { font: 500 11px/1.3 var(--font-ui); color: var(--zari-lt); margin-top: 3px; }

.drawer__logout { padding: 0 12px 16px; }
.drawer__logout .btn {
  width: 100%; min-height: 46px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font: 600 14px/1 var(--font-ui); color: var(--zari-lt);
  background: rgba(247,239,224,.04);
  border: 1px solid rgba(240,217,138,.28); border-radius: 12px;
  transition: background .16s ease, border-color .16s ease, color .16s ease;
}
.drawer__logout .btn:hover {
  background: rgba(166,43,55,.22); border-color: rgba(166,43,55,.5); color: var(--silk);
}
.drawer__logout .btn:active { transform: scale(.99); }

/* ---- entrance stagger + reduced-motion ------------------------------------ */
.drawer-toggle:checked ~ .drawer .drawer__head,
.drawer-toggle:checked ~ .drawer .drawer__body,
.drawer-toggle:checked ~ .drawer .admin-side-foot,
.drawer-toggle:checked ~ .drawer .drawer__logout {
  animation: drawer-rise .4s cubic-bezier(.22,.61,.36,1) both;
}
.drawer-toggle:checked ~ .drawer .drawer__body    { animation-delay: .04s; }
.drawer-toggle:checked ~ .drawer .admin-side-foot { animation-delay: .08s; }
.drawer-toggle:checked ~ .drawer .drawer__logout  { animation-delay: .1s; }

@keyframes drawer-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .drawer { transition: none; }
  .drawer-scrim { transition: none; }
  .drawer-toggle:checked ~ .drawer :is(.drawer__head, .drawer__body, .admin-side-foot, .drawer__logout) {
    animation: none;
  }
}

@media (max-width: 900px) {
  .hamburger-btn { display: inline-flex; }
}

/* --------------------------------------------------------------------------
   Combo box (SelectPicker) — type to filter, tap to choose.
   Hand-drawn rather than a native <datalist>, which Android renders inside the
   text box and iOS largely ignores. Rows are a full touch target because the
   weaver console is used one-thumbed on a phone.
   -------------------------------------------------------------------------- */
.combo { position: relative; }
.combo__input { padding-right: 42px; }

.combo__toggle {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  border: 0; border-radius: 50%; background: none;
  color: var(--muted); cursor: pointer;
}
.combo__toggle:hover { background: var(--silk-2); }
.combo__caret { font-size: 12px; line-height: 1; transition: transform .15s ease; }
.combo__caret.is-open { transform: rotate(180deg); }

.combo__list {
  position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 4px);
  margin: 0; padding: 4px; list-style: none;
  max-height: min(46vh, 288px); overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--paper); border: 1.5px solid var(--line);
  border-radius: var(--r-sm); box-shadow: 0 12px 28px rgba(43, 20, 24, .18);
}

.combo__option {
  display: flex; align-items: center; min-height: var(--touch-min);
  padding: 10px 12px; border-radius: 6px;
  font: 400 15px/1.3 var(--font-ui); color: var(--ink);
  cursor: pointer;
}
.combo__option.is-active,
.combo__option:hover { background: var(--silk-2); }
.combo__option[aria-selected="true"] { font-weight: 600; color: var(--plum, var(--ink)); }

/* Shown in place of the option rows when nothing matches. Not a row: it is not
   selectable, so it must not look like one. */
.combo__empty {
  padding: 12px; font: 400 13px/1.4 var(--font-ui);
  color: var(--muted, var(--ink)); opacity: .75; cursor: default;
}
