/* receipt_capture.css — styles for the Live Receipt Capture feature.

   This stylesheet is loaded via index.html AFTER components.css and
   the prior per-view stylesheets so it can consume the canonical
   Cambry tokens (--color-bg / --color-surface / --color-accent /
   --color-text / --color-text-muted / --color-on-accent) defined in
   styles.css.

   Slice 1 scope: the Capture_Mode_Selector segmented control + the
   layout glue for the Upload_Mode and Native_Camera_Mode panels. The
   live camera stream, OpenCV overlay, manual shutter, brightness
   hints, and progress ring all land in later slices and will append
   to this stylesheet then.

   Tokens consumed (defined in styles.css :root):
     --color-bg          slate background  (#1f2c38)
     --color-surface     card chrome       (#2a3a4a)
     --color-primary     darker fill       (#3a526a)
     --color-accent      soft pink         (#f896ff)
     --color-accent-hover lighter pink     (#ffb1ff)
     --color-on-accent   dark text on pink (#1f2c38)
     --color-text        cool white        (#e8edf0)
     --color-text-muted  muted blue-grey   (#a6b7bf)

   Validates: Requirements 1.6, 1.7, 12.1, 12.2, 12.3, 13.1, 13.3 */

/* ── Capture_Mode_Selector ────────────────────────────────────────── */

/* Wrapper — sits at the top of the receipt region and stretches edge
   to edge so the segmented control reads as the primary affordance
   for "how do I attach a receipt?" The 12 px radius matches the
   Cambry card surface treatment (Req 12.2). */
.receipt-mode-selector {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  gap: 4px;
  width: 100%;
  padding: 4px;
  background: var(--color-surface);
  border: 1px solid var(--color-primary);
  border-radius: 12px;
  font-family: 'Yantramanav', sans-serif;
}

/* Each segment is a real <button> for keyboard + screen-reader
   support (Req 13.3). The 44 × 44 minimum covers the ≥ 1936 CSS px²
   / ≥ 32 CSS px each-dimension target floor (Req 13.1) with margin —
   typical rendered width is well above the 32 px lower bound because
   the wrapper stretches each option to an equal share of the row.

   The bare <button> reset zeroes out the UA chrome; the visual
   treatment (slate idle, pink-on-slate active) lands on the modifier
   classes below. */
.receipt-mode-selector__option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 0;
  min-height: 44px;
  min-width: 44px;
  padding: 0.5rem 0.75rem;
  background: transparent;
  color: var(--color-text-muted);
  border: 1px solid transparent;
  border-radius: 8px;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-align: center;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease;
}

/* Hover treatment for the idle state — lifts the muted text to full
   white and tightens the border so the option feels live before the
   user commits. Active and focus states win over hover via cascade
   order below. */
.receipt-mode-selector__option:hover:not(:disabled) {
  color: var(--color-text);
  background: rgba(248, 150, 255, 0.06);
}

/* Keyboard focus ring (Req 13.3). The 2 px solid pink outline keeps
   the focus indicator visible against both the slate idle and the
   pink active treatments. The 2 px offset stops the outline from
   colliding with the rounded corners of the segment. */
.receipt-mode-selector__option:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Active segment — the option matching the currently-selected
   capture mode. Pink fill + slate text per Req 12.1 / 12.4. The
   ``aria-pressed="true"`` attribute on the button is the source of
   truth; we mirror it as a class because IE-era browsers sometimes
   choke on attribute selectors in the cascade. */
.receipt-mode-selector__option--active,
.receipt-mode-selector__option[aria-pressed="true"] {
  background: var(--color-accent);
  color: var(--color-on-accent);
  border-color: var(--color-accent);
  font-weight: 600;
}

.receipt-mode-selector__option--active:hover:not(:disabled),
.receipt-mode-selector__option[aria-pressed="true"]:hover:not(:disabled) {
  background: var(--color-accent-hover);
  color: var(--color-on-accent);
  border-color: var(--color-accent-hover);
}

/* ── Capture_Mode panel container ─────────────────────────────────── */

/* The panel below the selector that hosts whichever mode is active
   (Upload_Mode picker, Native_Camera_Mode picker — and in later
   slices, the Live_Capture_Mode video + overlay). Keeps a consistent
   12 px radius card chassis around whatever panel is mounted so the
   seam between selector and panel reads as one surface. */
.receipt-mode-panel {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* ── Slice 2 — Live Capture Mode ──────────────────────────────────── */

/* The Live_Capture_Mode tile reuses the existing
   ``.add-expense-sheet__capture-tile`` chassis from expenses.css for
   the rounded chrome, then layers on the geometry the live stream
   needs: positioning context for the overlay, fixed aspect ratio so
   the camera tile reads as the dominant affordance on the step, and
   the rounded 12 px clip so the inner <video> + overlay can't punch
   past the chassis edge.

   ``.receipt-capture-tile`` is the additive class
   ``mountLiveCapturePanel`` stacks alongside
   ``.add-expense-sheet__capture-tile`` so the live mode picks up the
   existing tile geometry (Req 4.6 / 12.2) without redeclaring
   anything that already lives in expenses.css. */
.receipt-capture-tile {
  position: relative;
  width: 100%;
  /* 4:3 keeps the receipt comfortably framed at the standard
     getUserMedia 640×480 resolution; the camera is allowed to
     produce wider streams (the <video> ``object-fit: cover``
     crop below absorbs the difference). */
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 12px;
  background: #000;
  /* Stops Safari from showing a default video controls overlay if
     the autoplay attribute fails for any reason. */
  isolation: isolate;
}

/* The live <video> fills the tile. ``object-fit: cover`` crops a
   landscape camera stream into the 4:3 frame without letterboxing,
   matching the user's expectation that the camera "fills" the tile.
   We disable pointer events so taps fall through to the overlay
   shutter button stacked on top (Req 9.1). */
.receipt-capture-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
  pointer-events: none;
}

/* The overlay container — absolutely positioned over the video so
   the corner-outline canvas, hint text, and shutter all share the
   same coordinate space as the video (Req 6.2 / 12.4). */
.receipt-capture-overlay {
  position: absolute;
  inset: 0;
  display: block;
  font-family: 'Yantramanav', sans-serif;
  color: var(--color-text);
  /* The overlay itself is non-interactive — its children opt back
     into pointer events explicitly. This keeps the underlying
     video unbothered by the canvas while letting the shutter and
     any future controls stay tappable. */
  pointer-events: none;
}

/* Corner outline canvas. Drawn each frame in JS based on the
   detection result. Sits at the back of the overlay stack so the
   shutter and hint text float over it. */
.receipt-capture-overlay__corners {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Hint text strip near the top of the overlay. Pill-shaped slate
   pill with cool-white type per Cambry tokens (Req 12.1 / 12.3 /
   13.2). The pill self-hides when the JS empties ``textContent``.
   Slice 5: smooth fade in/out via opacity transition so brightness
   hints don't pop into / out of existence as the meter crosses the
   gate threshold. ``visibility`` flips after the fade so the pill
   doesn't intercept ARIA reads when empty. */
.receipt-capture-overlay__hint {
  position: absolute;
  top: 0.75rem;
  left: 50%;
  transform: translateX(-50%);
  max-width: calc(100% - 1.5rem);
  padding: 0.4rem 0.85rem;
  background: rgba(31, 44, 56, 0.78);
  color: var(--color-text);
  border-radius: 999px;
  font-family: 'Yantramanav', sans-serif;
  font-size: 0.85rem;
  font-weight: 500;
  line-height: 1.2;
  text-align: center;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.18s ease;
}
/* Empty pill — fade out without removing layout space so the
   overlay doesn't shift when a transient hint disappears. */
.receipt-capture-overlay__hint:empty {
  opacity: 0;
  /* Setting visibility hidden under opacity 0 keeps assistive tech
     from announcing the empty pill; padding/border preserved so
     the layout stays stable across show/hide cycles. */
  visibility: hidden;
}

/* Slice 5 — persistent message channel.
   Used by ``CaptureOverlayUI.showHint`` (data-kind="hint") for the
   10-second no-stabilize copy and by ``showError`` (data-kind="error")
   for stream-ended / camera-error states. Distinct DOM node from
   ``__hint`` so the ephemeral brightness pill at the top of the
   overlay can coexist with a longer error/hint message in the
   center without one clobbering the other. */
.receipt-capture-overlay__message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-width: calc(100% - 1.5rem);
  padding: 0.6rem 1rem;
  background: rgba(31, 44, 56, 0.88);
  color: var(--color-text);
  border: 1px solid var(--color-primary);
  border-radius: 12px;
  font-family: 'Yantramanav', sans-serif;
  font-size: 0.95rem;
  font-weight: 500;
  line-height: 1.3;
  text-align: center;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.18s ease;
}
.receipt-capture-overlay__message:empty {
  opacity: 0;
  visibility: hidden;
}
/* Hint variant — softer, non-alarming pink-tinted border so the
   user reads it as guidance, not a failure. The shutter, corner
   outline, and brightness pill all keep working underneath this
   surface (Req 9.4 / Property 13).
   Positioned just above the manual shutter (rather than at the top
   of the overlay) so it sits in the user's natural focus path —
   "tap the shutter" reads better when the hint anchors near the
   target — and so it never collides with the ``__hint`` brightness
   pill at the top of the overlay (which keeps its own slot at
   ``top: 0.75rem``). */
.receipt-capture-overlay__message[data-kind="hint"] {
  background: rgba(31, 44, 56, 0.85);
  border-color: var(--color-accent);
  top: auto;
  bottom: calc(0.75rem + 64px + 0.5rem);
  transform: translate(-50%, 0);
}
/* Error variant — keeps the centered slate panel treatment so the
   user sees it without missing it on a dead stream. */
.receipt-capture-overlay__message[data-kind="error"] {
  background: var(--color-surface);
  border-color: var(--color-primary);
}

/* Slice 5 — Retry / Switch-to-Upload action row beneath the error
   message (Req 10.3). Centered horizontally below the message panel
   so the user sees the recovery affordances immediately. The row
   self-hides via ``:empty`` when no actions are wired (e.g. the
   default ``coordinator`` error path before Slice 5 retired the
   action-less ``showError`` call sites). */
.receipt-capture-overlay__error-actions {
  position: absolute;
  top: calc(50% + 2.5rem);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  max-width: calc(100% - 1.5rem);
  pointer-events: auto;
}
.receipt-capture-overlay__error-actions:empty {
  display: none;
}

/* Cambry pill buttons for the retry / switch action row. Pink fill
   (primary recovery affordance: Retry) + slate outline secondary
   (Switch to Upload). Both clear the ≥ 1936 CSS px² / ≥ 32 CSS px
   tap-target floor (Req 13.1) — 44 × 44 minimum is comfortably
   over with the rendered width set by the text content. */
.receipt-capture-overlay__retry-btn,
.receipt-capture-overlay__switch-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 0.45rem 1rem;
  border-radius: 999px;
  font-family: 'Yantramanav', sans-serif;
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease,
    transform 0.12s ease;
}

.receipt-capture-overlay__retry-btn {
  background: var(--color-accent);
  color: var(--color-on-accent);
  border: 1px solid var(--color-accent);
}
.receipt-capture-overlay__retry-btn:hover:not(:disabled) {
  background: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
}
.receipt-capture-overlay__retry-btn:active:not(:disabled) {
  transform: scale(0.96);
}
.receipt-capture-overlay__retry-btn:focus-visible {
  outline: 2px solid var(--color-text);
  outline-offset: 2px;
}

.receipt-capture-overlay__switch-btn {
  background: transparent;
  color: var(--color-text);
  border: 1px solid var(--color-text-muted);
}
.receipt-capture-overlay__switch-btn:hover:not(:disabled) {
  background: rgba(248, 150, 255, 0.08);
  border-color: var(--color-accent);
  color: var(--color-text);
}
.receipt-capture-overlay__switch-btn:active:not(:disabled) {
  transform: scale(0.96);
}
.receipt-capture-overlay__switch-btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Manual shutter button — fixed at the bottom of the capture tile,
   centered, and sized comfortably above the ≥ 1936 CSS px² /
   ≥ 32 CSS px tap-target floor (Req 9.3 / 13.1). 64×64 = 4096 px²,
   well over the floor with margin for partial taps.

   The button itself is the outer ring; the inner span is the dot.
   Pink fill, slate dot, matching Cambry's pill / FAB treatment. */
.receipt-capture-overlay__shutter {
  position: absolute;
  bottom: 0.75rem;
  left: 50%;
  transform: translateX(-50%);
  width: 64px;
  height: 64px;
  min-width: 32px;
  min-height: 32px;
  padding: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.92);
  border: 3px solid var(--color-accent);
  border-radius: 50%;
  cursor: pointer;
  pointer-events: auto;
  transition:
    transform 0.12s ease,
    background-color 0.15s ease,
    border-color 0.15s ease;
}

.receipt-capture-overlay__shutter:hover:not(:disabled) {
  background: #fff;
  border-color: var(--color-accent-hover);
}

.receipt-capture-overlay__shutter:active:not(:disabled) {
  transform: translateX(-50%) scale(0.94);
  background: #fff;
}

.receipt-capture-overlay__shutter:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

/* The inner pink dot. Decorative, ``aria-hidden`` set in JS. */
.receipt-capture-overlay__shutter-inner {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--color-accent);
  border-radius: 50%;
}

/* While the camera is still spinning up (`starting`) or the stream
   has errored, the shutter dims so the user understands tapping
   won't yet do anything. Pointer events stay on so a desperate user
   can still try. */
.receipt-capture-overlay[data-state="starting"] .receipt-capture-overlay__shutter,
.receipt-capture-overlay[data-state="error"] .receipt-capture-overlay__shutter {
  opacity: 0.55;
}

/* Loading row rendered while OpenCV.js is streaming in (Req 5.4).
   Mirrors the Cambry hint pill but centered in the tile so the
   user has visual confirmation the system is working during the
   ~1-2 second WASM load on a cold cache. */
.receipt-capture-loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 0.6rem 1rem;
  background: rgba(31, 44, 56, 0.8);
  color: var(--color-text);
  border: 1px solid var(--color-primary);
  border-radius: 999px;
  font-family: 'Yantramanav', sans-serif;
  font-size: 0.9rem;
  text-align: center;
  pointer-events: none;
}

/* ── Slice 5 — Polish: state visual treatments ────────────────────── */

/* Holding-state progress ring (Req 6.4 / 12.4).
   While the user is holding the framed receipt steady (all five
   Auto_Capture_Gates passing), a pink ring fills around the manual
   shutter as a visual countdown for the 600 ms stability duration.
   The keyframe sweeps ``stroke-dasharray``-style via a conic-gradient
   mask so we can stick to plain CSS without an SVG. The 600 ms
   duration matches ``DEFAULT_GATE_THRESHOLDS.stabilityDurationMs``
   in receipt_capture.js exactly. */
.receipt-capture-overlay[data-state="holding"] .receipt-capture-overlay__shutter {
  border-color: var(--color-accent);
  /* Layered conic gradient over the existing border so the ring
     reads as a fill effect on the existing chrome rather than a
     replacement element. ``--ring-progress`` is animated below. */
  background:
    conic-gradient(
      var(--color-accent) calc(var(--ring-progress, 0) * 1%),
      rgba(255, 255, 255, 0.92) 0
    );
  --ring-progress: 0;
  animation: receipt-capture-ring-fill 0.6s linear forwards;
}

@keyframes receipt-capture-ring-fill {
  from { --ring-progress: 0; }
  to   { --ring-progress: 100; }
}

/* Browsers that don't support animating CSS custom properties
   (older Safari) fall back to a simple opacity pulse so the
   ``holding`` state still reads as visually distinct. The
   ``@supports`` block flips the strategy when the @property
   registration is unavailable. */
@property --ring-progress {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

/* Captured flash animation (Req 6.5 / 12.4).
   When the coordinator fires a capture, the overlay briefly white-
   washes the camera feed so the user gets clear visual confirmation
   that the shutter fired (the audio shutter sound is intentionally
   suppressed since the camera is muted for autoplay). 150 ms keeps
   the flash visible without dominating the transition into the
   downstream preview. */
.receipt-capture-overlay[data-state="captured"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: #ffffff;
  pointer-events: none;
  animation: receipt-capture-flash 0.15s ease-out forwards;
  /* Stack above the corner outline + hint pill so the flash reads
     as a full-overlay event. */
  z-index: 2;
}

@keyframes receipt-capture-flash {
  from { opacity: 0.85; }
  to   { opacity: 0; }
}

/* Hide the manual shutter after capture — the captured frame is
   now in the preview region downstream and re-tapping the shutter
   would only enqueue another upload. The existing ``destroyed``
   latch on the orchestrator already prevents double-fires; this
   visual hide is belt-and-suspenders for the moment between the
   capture event and the orchestrator tearing the panel down. */
.receipt-capture-overlay[data-state="captured"] .receipt-capture-overlay__shutter {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease-out;
}

/* Smooth state transitions across the overlay corner outline so
   detected → holding doesn't snap visibly between neutral and pink.
   The corner canvas redraws on every frame, but keeping the parent
   surface's opacity transition smooth covers the flicker between
   ``searching`` and ``detected`` when the contour pops in. */
.receipt-capture-overlay__corners {
  transition: opacity 0.12s ease;
}
.receipt-capture-overlay[data-state="error"] .receipt-capture-overlay__corners {
  opacity: 0.25;
}

/* When the coordinator fires the no-stabilize hint, surface the
   accent border on the manual shutter so the user has a clear
   visual cue that "tapping this is the suggested next action".
   Distinct from the holding state's progress-fill treatment so the
   two never visually conflict. */
.receipt-capture-overlay
  .receipt-capture-overlay__message[data-kind="hint"]
  ~ .receipt-capture-overlay__shutter {
  box-shadow: 0 0 0 4px rgba(248, 150, 255, 0.25);
}
