/* ==========================================================================
   Shaniwarwada e-Review — shared stylesheet
   --------------------------------------------------------------------------
   Single-screen ("one frame") layout. Every screen is exactly one viewport
   tall and does not scroll: the decorative maroon/gold border stays pinned
   around the content the whole time, the way the printed visitor book and the
   kiosk app look.

   How that is achieved, in one place so it is not re-derived per page:

     body      locked to the viewport, never scrolls.
     .page     height: 100dvh, a flex column. dvh (not vh) so the phone's
               collapsing address bar does not leave a dead strip.
     .grow     the ONE flexible child per screen — the textarea, the camera,
               the fort — which absorbs whatever height is left over. Always
               paired with min-height: 0, or a flex child refuses to shrink
               below its content and pushes the page taller than the screen.

   .page keeps overflow-y: auto purely as a safety valve. On a normal phone
   nothing overflows so nothing scrolls; on a very short screen with the
   keyboard open it scrolls a little rather than hiding the submit button
   somewhere unreachable.
   ========================================================================== */

/* ── Palette ─────────────────────────────────────────────────────────────
   Lifted from the Flutter app AppColors so the web app and the kiosk app
   are the same colour, not "close enough". */
:root {
  --maroon:       #8A1B22;
  --maroon-deep:  #5E1116;
  --gold:         #C8902F;
  --gold-bright:  #F6CE73;
  --gold-deep:    #8A5A0E;
  --ivory:        #FBF9F3;
  --ink:          #3E2B23;
  --ink-muted:    #7A6A58;
  --panel:        #FFFFFF;
  --line:         #E6D9C2;
  --danger:       #B3261E;
  --ok:           #1E7A3C;

  --radius:       11px;
  --radius-sm:    8px;
  --tap:          46px;            /* minimum comfortable tap target */
  --frame-gap:    9px;             /* inset of the decorative frame */
  --gap:          9px;             /* rhythm between stacked blocks */
  --shadow:       0 2px 9px rgba(94, 17, 22, .10);
  --shadow-lg:    0 8px 28px rgba(94, 17, 22, .18);

  --font: "Noto Sans Devanagari", "Nirmala UI", "Kohinoor Devanagari",
          "Mangal", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

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

/* The hidden attribute must win over every layout rule below. Without this a
   `display: flex` class beats the browser default `[hidden] { display:none }`
   on specificity, and elements the script has hidden — the sign-in card, the
   camera preview behind a playback — stay on screen. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  height: 100%;
  overflow: hidden;                /* the page itself never scrolls */
  font-family: var(--font);
  color: var(--ink);
  background: var(--ivory);
  /* The artwork is warm ivory, not white — a plain white page would make the
     extracted fort look like a sticker stuck on the screen. */
  -webkit-tap-highlight-color: rgba(138, 27, 34, .12);
}

/* Stop iOS from zooming when a field is focused: anything under 16px triggers
   the zoom, and the page never zooms back out on its own. */
input, textarea, select, button { font: inherit; font-size: 16px; }

img { max-width: 100%; display: block; }

/* ── The decorative frame ────────────────────────────────────────────────
   Two hairlines (maroon outside, gold inside) pinned to the viewport, with
   the lotus and leaf ornaments sitting on top of them. Drawn in CSS rather
   than shipped as one big border image so it stays crisp at any screen size
   and costs nothing to render. */
.frame {
  position: fixed;
  inset: var(--frame-gap);
  border: 1.5px solid var(--maroon);
  pointer-events: none;
  z-index: 5;
  /* Two solid ivory rings — one outside the maroon rule, one filling the gap
     in to the gold rule — so anything that does move behind the border is cut
     cleanly. The ornaments and corner diamonds are child elements, so they
     still paint on top of both. */
  box-shadow:
    0 0 0 var(--frame-gap) var(--ivory),
    inset 0 0 0 4px var(--ivory);
}
.frame::after {
  content: "";
  position: absolute;
  inset: 4px;
  border: 1px solid var(--gold);
}

/* Corner diamonds — small rotated squares that sit over the inner gold line,
   the way the printed border turns its corners. */
.frame i {
  position: absolute;
  width: 7px; height: 7px;
  background: var(--gold);
  transform: rotate(45deg);
}
.frame i:nth-child(1) { top: 1px;    left: 1px; }
.frame i:nth-child(2) { top: 1px;    right: 1px; }
.frame i:nth-child(3) { bottom: 1px; left: 1px; }
.frame i:nth-child(4) { bottom: 1px; right: 1px; }

/* Lotus on the top and bottom rails, leaf fans on the side rails. Each one
   carries an ivory backing so it visually breaks the hairline it sits on,
   exactly as the artwork does. */
.frame b {
  position: absolute;
  background: no-repeat center / contain;
  background-color: var(--ivory);
}
.frame .lotus-top,
.frame .lotus-bottom {
  left: 50%;
  width: 50px; height: 24px;
  margin-left: -25px;
  padding: 0 7px;
  background-image: url("../assets/lotus.png");
}
.frame .lotus-top    { top: -10px; }
.frame .lotus-bottom { bottom: -10px; transform: rotate(180deg); }

.frame .leaf-left,
.frame .leaf-right {
  top: 50%;
  width: 20px; height: 42px;
  margin-top: -21px;
  padding: 7px 0;
  background-image: url("../assets/leaf.png");
}
.frame .leaf-left  { left: -9px; }
.frame .leaf-right { right: -9px; transform: rotate(180deg); }

/* ── Page shell ──────────────────────────────────────────────────────────*/
.page {
  position: relative;
  z-index: 1;
  max-width: 520px;
  margin: 0 auto;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  padding: 20px 20px max(16px, env(safe-area-inset-bottom));
  overflow-y: auto;                /* safety valve only — see file header */
  overscroll-behavior: contain;
}
.page--wide { max-width: 1180px; }

/* The single flexible child that soaks up the leftover height. */
.grow { flex: 1 1 auto; min-height: 0; }

/* Blocks that must keep their natural height no matter how tight it gets. */
.fixed { flex: 0 0 auto; }

/* ── Masthead: the two authority logos with the Ganesh crest between ─────*/
.masthead {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 10px;
}
.masthead img.logo    { width: clamp(38px, 12vw, 54px); height: auto; justify-self: start; }
.masthead img.logo--r { justify-self: end; }
.masthead img.crest   { width: clamp(28px, 9vw, 40px); height: auto; }

/* ── Type ────────────────────────────────────────────────────────────────*/
.title {
  flex: 0 0 auto;
  margin: 0;
  font-size: clamp(17px, 5vw, 23px);
  line-height: 1.3;
  font-weight: 800;
  text-align: center;
  color: var(--maroon);
  letter-spacing: .2px;
}
/* The form headings carry a thin gold rule instead of the full lotus divider:
   the same ceremony at a third of the height. */
.title--sm { font-size: clamp(15px, 4.4vw, 19px); }
.title--sm::after {
  content: "";
  display: block;
  width: 62px;
  height: 1.5px;
  margin: 7px auto 0;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
.subtitle {
  flex: 0 0 auto;
  margin: 0;
  font-size: clamp(12.5px, 3.5vw, 15.5px);
  line-height: 1.45;
  font-weight: 600;
  text-align: center;
  color: var(--maroon-deep);
}
.muted { color: var(--ink-muted); font-size: 12px; line-height: 1.45; }
.center { text-align: center; }

/* The gold lotus rule used to separate blocks. */
.divider {
  flex: 0 0 auto;
  width: min(260px, 70%);
  margin: 0 auto;
  height: 15px;
  background: url("../assets/divider.png") no-repeat center / contain;
}

/* ── The fort ────────────────────────────────────────────────────────────
   Sized by its own proportions, NOT stretched to soak up leftover height.
   It used to be the flexible block, but a background image can only ever be
   as wide as its column, so on a tall screen the box grew and the artwork
   stayed put at the bottom of it — leaving a large dead gap above the fort.

   The leftover height is handed to the content instead, via the auto margins
   below, which spread it evenly above and below the middle of the screen. */
.fort-fill {
  flex: 0 1 auto;
  width: calc(100% + 12px);
  margin: 0 -6px;
  aspect-ratio: 1200 / 515;      /* the real proportions of fort.webp */
  max-height: 32dvh;
  min-height: 48px;
  background: url("../assets/fort.webp") no-repeat center bottom / contain;
}

/* Absorbs the slack on a screen taller than the content needs, splitting it
   equally above and below so the block sits optically centred rather than
   piling all the empty space into one gap. */
.slack       { margin-block: auto; }
.slack-start { margin-top: auto; }
.slack-end   { margin-bottom: auto; }

/* The form screens deliberately carry NO fort watermark. It was tried behind
   the fields: the review box, the camera and the details panel are all opaque,
   so all that showed was a sliver of line-work in the gaps between them, which
   read as a smudge rather than as artwork. The decorative frame carries the
   identity on these two screens; the fort belongs to the welcome and thank-you
   pages where it has room to be seen whole.

   To bring it back, add <div class="watermark"></div> before <main> and
   restore a rule here. */

.footer-logos {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}
.footer-logos img         { width: clamp(32px, 10vw, 44px); height: auto; }
.footer-logos img.digirev { width: clamp(52px, 16vw, 70px); }

/* ── Top bar on the inner screens ────────────────────────────────────────*/
.topbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* ── Language chooser ────────────────────────────────────────────────────*/
.lang-label {
  flex: 0 0 auto;
  margin: 0;
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  color: var(--maroon);
}
.lang-row {
  flex: 0 0 auto;
  display: flex;
  justify-content: center;
  gap: 6px;
  flex-wrap: wrap;
}
.lang-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 6px 13px;
  border: 1.2px solid var(--gold);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--maroon);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.lang-btn[aria-pressed="true"] {
  background: var(--maroon);
  border-color: var(--maroon);
  color: #fff;
}
/* One segmented control in the form top bars rather than three loose pills —
   fewer outlines on screen, and it reads as a single control. */
.lang-row--mini {
  gap: 0;
  border: 1px solid var(--gold);
  border-radius: 999px;
  overflow: hidden;
  background: var(--panel);
  box-shadow: 0 1px 3px rgba(138, 90, 14, .10);
}
.lang-row--mini .lang-btn {
  border: 0;
  border-radius: 0;
  min-height: 30px;
  padding: 4px 11px;
  font-size: 12.5px;
}
.lang-row--mini .lang-btn + .lang-btn { border-left: 1px solid rgba(200, 144, 47, .45); }
.lang-row--mini .lang-btn .ico { display: none; }

/* ── Buttons ─────────────────────────────────────────────────────────────*/
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  min-height: var(--tap);
  padding: 11px 16px;
  border: 0;
  border-radius: var(--radius);
  /* A shallow gradient and a hairline of light along the top edge: the button
     catches the light the way the gilt on the artwork does, instead of sitting
     flat on the page. */
  background: linear-gradient(180deg, #97232A 0%, var(--maroon) 55%, #7E171E 100%);
  color: #fff;
  font-weight: 700;
  font-size: 16px;
  line-height: 1.25;
  letter-spacing: .2px;
  text-decoration: none;
  cursor: pointer;
  box-shadow:
    0 2px 10px rgba(94, 17, 22, .20),
    inset 0 1px 0 rgba(255, 255, 255, .12);
  transition: transform .08s, box-shadow .15s, filter .15s;
}
.btn:active { transform: translateY(1px); box-shadow: none; filter: brightness(.96); }
.btn:disabled, .btn[aria-disabled="true"] {
  background: #DCC8C9;
  color: #FBF3F3;
  box-shadow: none;
  cursor: not-allowed;
}
.btn--ghost {
  background: var(--panel);
  color: var(--maroon);
  border: 1px solid var(--gold);
  box-shadow: 0 1px 3px rgba(138, 90, 14, .10);
}
.btn--danger { background: var(--danger); }
.btn--stop   { background: var(--maroon-deep); }
.btn--sm     { width: auto; min-height: 34px; padding: 6px 12px; font-size: 13.5px; }
.btn .ico    { width: 20px; height: 20px; flex: 0 0 auto; }

/* The two big choices on the landing screen. The auto block margins park them
   in the middle of whatever room is left between the language row and the
   fort, so a tall screen reads as generous spacing rather than as one large
   hole above the artwork. */
.choice-grid {
  flex: 0 1 auto;
  display: grid;
  /* Always two across, on every width. Side by side they read as a single
     "pick one" choice; stacked they read as a list to work through. */
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  min-height: 0;
  margin-block: auto;
}
/* The buttons take a share of a tall screen's extra height too, so the room
   left over reads as generous spacing rather than as emptiness. */
.choice-grid .btn {
  flex-direction: column;
  gap: 8px;
  /* Narrow side padding, and the label is free to wrap onto a second line —
     "व्हिडिओ अभिप्राय" is a wide phrase in a half-width button on a 320px
     phone, and wrapping reads better than shrinking the type further. */
  padding: 14px 9px;
  min-height: clamp(66px, 13dvh, 130px);
  font-size: clamp(13.5px, 3.9vw, 18px);
  text-align: center;
  line-height: 1.3;
  text-wrap: balance;
}
.choice-grid .btn .ico { width: clamp(22px, 6vw, 28px); height: clamp(22px, 6vw, 28px); }

/* ── Form fields ─────────────────────────────────────────────────────────
   The forms carry no separate labels. Every field wears its label as its own
   placeholder with a small gold glyph inside the box — which is exactly how
   the printed design and the kiosk app draw them. That removes four label
   rows from each screen, and those rows were both the clutter and the reason
   the screens were tight.

   `min-width: 0` on every grid child is not cosmetic: without it a long label
   or placeholder sets a content-based minimum, the 1fr columns refuse to
   shrink, and the row pushes out past the decorative frame. */
.field { flex: 0 0 auto; min-width: 0; }

/* Kept for the section headings above the signature pad. Small, letter-spaced
   and quiet, so it reads as a caption and not as another shouted label. */
.field-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .7px;
  text-transform: uppercase;
  color: var(--gold-deep);
}
.req { color: var(--danger); }

/* Name, date and phone each take a full-width row of their own. They were
   tried two-up: a native date control reports a much wider intrinsic size
   than the date it shows (~155px for ten characters), which left the phone
   box beside it too narrow for a ten-digit number on a small phone. One
   field per row is both roomier and easier to read down. */

/* A soft grouping for the visitor details. Not a card — no heavy border, no
   drop shadow — just a warm tint and a hairline, enough to say "these belong
   together" without adding the bulk a card would. */
.panel {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 11px;
  border: 1px solid rgba(200, 144, 47, .32);
  border-radius: var(--radius);
  background: rgba(255, 253, 248, .82);
  min-width: 0;
}

.input, .textarea, select.input {
  width: 100%;
  min-width: 0;
  min-height: var(--tap);
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--ink);
  outline: none;
  transition: border-color .16s, box-shadow .16s;
}
/* Placeholders sit a shade smaller than typed text — it reads as a hint
   rather than as content, and it keeps the longer labels from clipping. The
   input's own font-size stays at 16px, which is what iOS checks before it
   decides to zoom the page on focus. */
.input::placeholder, .textarea::placeholder { color: #B6AA98; font-size: 13.5px; }
.input:focus, .textarea:focus {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(200, 144, 47, .16);
}
.input.is-error, .textarea.is-error { border-color: var(--danger); }

/* Field with a glyph inside it. The icon is injected by App.init() from the
   wrapper's data-icon, so the markup stays one line per field. */
.ifield { position: relative; min-width: 0; }
.ifield > .ico {
  position: absolute;
  left: 10px;
  top: 50%;
  width: 16px;
  height: 16px;
  margin-top: -8px;
  color: var(--gold-deep);
  opacity: .85;
  pointer-events: none;
  z-index: 1;
}
/* Clears the glyph (10px in, 16px wide) with 6px of air after it. */
.input--icon { padding-left: 32px; }

/* The date box already carries our calendar glyph on the left, so the native
   one would be a second identical icon. It is made invisible and stretched
   over the whole control instead — which also means tapping anywhere in the
   field opens the picker, rather than only that small button. */
input[type="date"].input--icon { padding-right: 10px; }
input[type="date"].input--icon::-webkit-calendar-picker-indicator {
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
}

/* ── The review box ──────────────────────────────────────────────────────
   The flexible block on the written-review screen. The counter floats in its
   bottom corner instead of sitting on a row of its own. */
.textarea-wrap { position: relative; display: flex; flex-direction: column; min-width: 0; }
.textarea {
  flex: 1 1 auto;
  height: 100%;
  min-height: 88px;
  padding: 13px 15px 26px;
  resize: none;
  line-height: 1.6;
  background:
    linear-gradient(#fff, #fff) padding-box,
    linear-gradient(160deg, rgba(200,144,47,.30), rgba(200,144,47,.10)) border-box;
  border: 1px solid transparent;
  box-shadow: inset 0 1px 3px rgba(94, 17, 22, .045);
}
.char-count {
  position: absolute;
  right: 12px;
  bottom: 8px;
  font-size: 10.5px;
  letter-spacing: .3px;
  color: #BCB0A0;
  background: #fff;
  padding-left: 6px;
  pointer-events: none;
}

/* ── Identity row: selfie button beside the name field ───────────────────*/
.id-row {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  align-items: center;
  min-width: 0;
}

/* A round gold-ringed button rather than a dashed square: it reads as a
   portrait slot, and it sits level with the name field beside it. */
.photo-tile {
  position: relative;
  width: var(--tap);
  height: var(--tap);
  border: 1.4px solid var(--gold);
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, #FFFDF7, #FBF3E2);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--gold-deep);
  cursor: pointer;
  /* Visible, not hidden: the remove badge hangs off the corner, and a circular
     clip would slice it in half. The photo is rounded on its own instead. */
  overflow: visible;
  flex: 0 0 auto;
  box-shadow: 0 1px 4px rgba(138, 90, 14, .14);
  transition: box-shadow .16s, border-color .16s;
}
.photo-tile:active { box-shadow: none; }
.photo-tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}
.photo-tile .ico { width: 21px; height: 21px; }
.photo-tile.has-photo { border-color: var(--maroon); }
.photo-clear {
  position: absolute;
  top: -5px; right: -5px;
  width: 20px; height: 20px;
  display: none;
  align-items: center;
  justify-content: center;
  border: 1.5px solid var(--ivory);
  border-radius: 50%;
  background: var(--maroon);
  color: #fff;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  z-index: 2;
}
.photo-tile.has-photo .photo-clear { display: flex; }

/* ── Signature pad ───────────────────────────────────────────────────────*/
.sig-block { flex: 0 0 auto; min-width: 0; }
.sig-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 5px;
}
.sig-wrap {
  position: relative;
  border: 1px solid rgba(200, 144, 47, .32);
  border-radius: var(--radius-sm);
  background: #fff;
  overflow: hidden;
  box-shadow: inset 0 1px 3px rgba(94, 17, 22, .045);
}
/* The ruled line a signature is written on, drawn in the box rather than
   asked for in words. */
.sig-wrap::after {
  content: "";
  position: absolute;
  left: 16px; right: 16px;
  bottom: 26%;
  border-bottom: 1px dashed rgba(138, 90, 14, .30);
  pointer-events: none;
}
/* touch-action: none is what stops the browser panning the page while a
   finger is drawing the signature. */
.sig-wrap canvas {
  display: block;
  position: relative;
  z-index: 1;
  width: 100%;
  height: clamp(52px, 9dvh, 84px);
  touch-action: none;
}
.sig-hint {
  position: absolute;
  left: 0; right: 0;
  bottom: 26%;
  margin-bottom: 5px;
  text-align: center;
  color: #C4B8A6;
  font-size: 12.5px;
  pointer-events: none;
}
.sig-wrap.has-ink .sig-hint,
.sig-wrap.has-ink::after { display: none; }

/* A quiet text action, so "Clear" does not compete with Submit. */
.link-btn {
  border: 0;
  background: none;
  padding: 2px 4px;
  color: var(--maroon);
  font-size: 12.5px;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(138, 27, 34, .35);
  cursor: pointer;
}
.link-btn:active { color: var(--maroon-deep); }

/* ── Video review ────────────────────────────────────────────────────────*/
.video-stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 120px;
  background: #17100C;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1.2px solid var(--line);
}
.video-stage video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #17100C;
}
/* The live preview is mirrored so it behaves like a mirror while recording;
   the saved file and the playback are NOT mirrored, or text held up to the
   camera would read backwards. */
.video-stage video.is-mirrored { transform: scaleX(-1); }

.rec-badge {
  position: absolute;
  top: 8px; left: 8px;
  display: none;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(23, 16, 12, .74);
  color: #fff;
  font-size: 12.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.rec-badge.on { display: inline-flex; }
.rec-badge .dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #FF4136;
  animation: blink 1s steps(2, start) infinite;
}
@keyframes blink { to { visibility: hidden; } }
@media (prefers-reduced-motion: reduce) { .rec-badge .dot { animation: none; } }

.cam-flip {
  position: absolute;
  top: 8px; right: 8px;
  width: 36px; height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: rgba(23, 16, 12, .62);
  color: #fff;
  cursor: pointer;
}
.time-left {
  position: absolute;
  bottom: 8px; right: 8px;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(23, 16, 12, .70);
  color: #FFEFD0;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.video-actions { flex: 0 0 auto; display: grid; gap: 8px; }
.video-actions.two-up { grid-template-columns: 1fr auto; align-items: center; }

/* ── Visitor number badge ────────────────────────────────────────────────*/
.visitor-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 7px 13px;
  border: 1.3px solid var(--gold);
  border-radius: 999px;
  background: var(--panel);
  color: var(--maroon);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: .5px;
  white-space: nowrap;
}
.visitor-badge--xl {
  font-size: clamp(17px, 5.2vw, 22px);
  padding: 11px 24px;
  letter-spacing: 1.2px;
}

/* ── Alerts ──────────────────────────────────────────────────────────────*/
.alert {
  flex: 0 0 auto;
  display: none;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid;
  font-size: 13px;
  line-height: 1.45;
}
.alert.show   { display: block; }
.alert--err   { background: #FDECEA; border-color: #F3C4BF; color: #8A1B22; }
.alert--ok    { background: #E9F6EE; border-color: #BEE3CB; color: #14602F; }
.alert--info  { background: #FFF7E8; border-color: #F0DDB4; color: #6B4A0E; }

/* Full-screen "saving…" cover, so nobody double-taps submit. */
.busy {
  position: fixed;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 14px;
  background: rgba(251, 249, 243, .93);
  z-index: 60;
  color: var(--maroon);
  font-weight: 700;
}
.busy.show { display: flex; }
.spinner {
  width: 40px; height: 40px;
  border: 3.5px solid rgba(200, 144, 47, .28);
  border-top-color: var(--maroon);
  border-radius: 50%;
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Thank you ───────────────────────────────────────────────────────────*/
.tick {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(52px, 15vw, 66px);
  height: clamp(52px, 15vw, 66px);
  /* margin-inline, not the margin shorthand: the shorthand would reset the
     block margins and cancel the .slack-start auto margin that shares out a
     tall screen's spare height. */
  margin-inline: auto;
  border-radius: 50%;
  background: #E9F6EE;
  border: 1.6px solid #BEE3CB;
  color: #14602F;
}
.tick svg { width: 55%; height: 55%; }

/* ══ Admin ═══════════════════════════════════════════════════════════════*/
.login-wrap {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--gap);
  max-width: 380px;
  width: 100%;
  margin: 0 auto;
}

.admin-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.admin-bar .grow-x { flex: 1 1 180px; min-width: 0; }
.admin-bar .input { min-height: 38px; padding: 7px 11px; }

.stats {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.stat {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 7px 10px;
}
.stat b { display: block; font-size: 19px; color: var(--maroon); line-height: 1.15; }
.stat span { font-size: 11.5px; color: var(--ink-muted); }

/* The register is the flexible block: the chrome around it stays put and the
   rows scroll inside, so the admin screen is also exactly one frame. */
.table-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--gold);
  border-radius: var(--radius-sm);
  background: var(--panel);
}
table.reviews { width: 100%; border-collapse: collapse; min-width: 820px; font-size: 13.5px; }
table.reviews thead th {
  background: var(--maroon-deep);
  color: #FFEFD0;
  text-align: left;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .3px;
  padding: 9px 11px;
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
}
table.reviews td { padding: 9px 11px; border-top: 1px solid var(--line); vertical-align: top; }
table.reviews tbody tr:nth-child(even) { background: #FFFDF7; }
table.reviews .no { font-weight: 800; color: var(--maroon); white-space: nowrap; }
table.reviews .thumb {
  width: 50px; height: 50px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: #F4EFE4;
}
table.reviews .sig { width: 84px; height: 40px; object-fit: contain; }
table.reviews .rtext {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-width: 360px;
  line-height: 1.45;
  cursor: pointer;
  color: var(--ink);
}
table.reviews .rtext:hover { color: var(--maroon); }
.tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}
.tag--text  { background: #FFF3DA; color: #8A5A0E; border: 1px solid #F0DDB4; }
.tag--video { background: #FCE9EA; color: #8A1B22; border: 1px solid #F0C2C5; }
.dash { color: #C9BFAE; }

.video-cell { display: flex; align-items: center; gap: 9px; cursor: pointer; }
.video-cell .play {
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--maroon);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}

.pager {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}
.pager span { font-size: 13px; color: var(--ink-muted); }

.empty { padding: 34px 20px; text-align: center; color: var(--ink-muted); }

/* ── Modal (review detail / video playback) ──────────────────────────────*/
.modal {
  position: fixed;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(35, 22, 18, .62);
  z-index: 70;
}
.modal.show { display: flex; }
.modal__box {
  background: var(--ivory);
  border: 1.4px solid var(--gold);
  border-radius: var(--radius);
  max-width: 600px;
  width: 100%;
  max-height: 88dvh;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.modal__head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 14px;
  background: var(--maroon-deep);
  color: #FFEFD0;
  font-weight: 700;
}
.modal__close {
  width: 32px; height: 32px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 239, 208, .16);
  color: #FFEFD0;
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
}
.modal__body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 14px; }
/* A portrait phone clip is 3:4, so at full modal width it would stand taller
   than the dialog and push its own controls out of reach. Capped and letter-
   boxed instead. */
.modal__body video {
  width: 100%;
  max-height: 52dvh;
  object-fit: contain;
  border-radius: var(--radius-sm);
  background: #000;
}
.modal__body .review-body { white-space: pre-wrap; line-height: 1.6; font-size: 15px; }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 5px 13px; font-size: 13.5px; margin-bottom: 12px; }
.kv dt { color: var(--ink-muted); }
.kv dd { margin: 0; font-weight: 600; }

/* Visually hidden but still read out by screen readers. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ══ Short screens ═══════════════════════════════════════════════════════
   An iPhone SE with the keyboard up leaves barely 400px. Everything that can
   give, gives: the page title and the ornamental dividers go,
   and the rhythm tightens. The fields and the submit button never shrink
   below a comfortable tap target. */
@media (max-height: 660px) {
  :root { --gap: 6px; }
  .page { padding: 12px 14px max(10px, env(safe-area-inset-bottom)); }
  .divider { display: none; }
  .masthead img.logo  { width: 38px; }
  .masthead img.crest { width: 28px; }
}

@media (max-height: 560px) {
  .title--sm { display: none; }
  .frame b   { display: none; }
  .stats     { grid-template-columns: repeat(4, 1fr); }
  .stat b    { font-size: 16px; }
}

/* ══ Narrow screens ══════════════════════════════════════════════════════
   A 10-digit phone number is wider than the hint it replaces, so the field
   has to be measured against the typed value, not the placeholder. Below
   380px the gutters give up a few pixels to make room for it. */
@media (max-width: 380px) {
  .page  { padding-inline: 14px; }
  .panel { padding: 9px; }
}

/* Under ~500px there is not enough room for both a label and the field it
   labels. The placeholders already say the same thing ("तुमचे पूर्ण नाव",
   "१० अंकी मोबाइल नंबर"), so the labels go and the controls shrink to the
   smallest size that is still comfortably tappable. */
@media (max-height: 500px) {
  :root { --tap: 40px; --gap: 5px; }
  .field-label      { display: none; }
  .input            { min-height: 40px; padding: 8px 11px; }
  .video-stage      { min-height: 84px; }
  .sig-wrap canvas  { height: 42px; }
  .char-count       { display: none; }
  .choice-grid .btn { min-height: 58px; }
}

/* A small phone in portrait with the keyboard open leaves barely 420px. The
   camera preview and the signature pad give up the last of their height —
   neither is what the visitor is looking at while they type their name, and
   both spring back the moment the keyboard closes. */
@media (max-height: 440px) and (max-width: 619px) {
  :root                  { --gap: 4px; }
  .video-stage           { min-height: 46px; }
  .sig-wrap canvas       { height: 32px; }
  .topbar .btn--sm       { min-height: 30px; }
  .video-actions .btn    { min-height: 38px; }
}

/* On the narrowest phones the date and phone take a row each (see the width
   rules above), and the video screen has no spare row to give. The camera
   preview funds it — the fields have to be readable, the preview only has to
   show the visitor roughly where they are in frame. */
@media (max-width: 349px) {
  .video-stage { min-height: 96px; }
}
@media (max-width: 349px) and (max-height: 500px) {
  .video-stage { min-height: 50px; }
}

/* A phone held sideways: the frame ornaments crowd a 360px-tall viewport. */
@media (max-height: 480px) {
  :root { --frame-gap: 5px; }
  .masthead     { display: none; }
  .tick         { display: none; }
  .fort-fill    { min-height: 0; }
  .footer-logos { display: none; }
  .subtitle     { display: none; }
}

/* ══ Landscape ═══════════════════════════════════════════════════════════
   Held sideways (or on a wall-mounted tablet) there is width to spare and no
   height at all, so the two form screens split in two: the flexible block —
   the camera, or the review box — takes the left column full height, and the
   fields stack down the right. This is the shape the printed design and the
   kiosk app already use. */
/* In portrait the two column wrappers are not there at all — display: contents
   removes them from layout, so their children stay direct flex items of the
   form exactly as if the wrappers had never been written. They only become
   real boxes in the landscape rule below. */
.col-media,
.col-fields { display: contents; }

@media (orientation: landscape) and (max-height: 560px) and (min-width: 620px) {
  .page { max-width: 920px; }

  #form {
    flex-direction: row !important;
    gap: 12px !important;
  }
  .col-media,
  .col-fields {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    min-height: 0;
  }
  .col-media  { flex: 1.15 1 0; }
  .col-fields { flex: 1 1 0; overflow-y: auto; }

  /* There is room for the labels again in this layout. */
  .field-label { display: block; }
}
