/* Valucher public web UI — brand theming on top of Bootstrap 5.
   Palette and typography mirror docs/product/brief.md §4. */

:root {
  --v-green-main: #214F28;
  --v-green-2: #306F36;   /* default card bg, footer, header bg */
  --v-green-3: #469A47;
  --v-citrus: #FEB719;    /* progress bars, CTAs, accents */
  --v-ink: #181516;       /* default text */
  --v-grey-light: #F1F1EF;
  --v-grey-bg: #FAF9F9;   /* page background */
  --v-grey-footer: #E9E7E4;  /* neutral footer — stays out of the way of org card theming */
  --v-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
}

html, body { min-height: 100%; }
body {
  font-family: "Quicksand", system-ui, sans-serif;
  background: var(--v-grey-bg);
  color: var(--v-ink);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
main { flex: 1 0 auto; }

h1, h2, h3, h4, h5, .navbar-brand { font-weight: 600; }

/* Brand surfaces */
/* White bar with the wordmark logo. A hairline keeps it from floating on the off-white page. */
.navbar { background: #fff; border-bottom: 1px solid rgba(24, 21, 22, .08); }
.navbar-logo { height: 34px; width: auto; flex: none; }
/* Once the page is scrolled the wordmark collapses to just the stylised V. The brand is a clipping
   window (max-width animates from the full logo width down to the V mark, which sits at the left of
   the image), so the leading V stays put while "alucher" slides out of view. */
.navbar-brand { display: inline-flex; overflow: hidden; max-width: 222px; transition: max-width .25s ease; }
.navbar.is-scrolled .navbar-brand { max-width: 54px; }

/* Language switch — the trigger shows just the current flag; the menu lists flag + label, active locale marked. */
.lang-switch .lang-toggle {
  padding: .25rem .55rem; border: 1px solid rgba(24, 21, 22, .15); border-radius: .375rem;
  background: transparent; color: var(--v-ink); font-size: .9rem; cursor: pointer;
  transition: background-color .15s ease;
}
.lang-switch .lang-toggle:hover { background: rgba(24, 21, 22, .04); }
.lang-switch .dropdown-item.lang-btn { display: flex; align-items: center; cursor: pointer; }
.lang-switch .dropdown-item.lang-btn.active { background: var(--v-green-main); color: #fff; }
.lang-switch .fi { width: 1.5em; height: 1.12em; border-radius: 2px; box-shadow: 0 0 0 1px rgba(0,0,0,.15); }
.navbar .nav-link { color: var(--v-ink); }
.navbar .nav-link:hover, .navbar .nav-link.active { color: var(--v-green-main); }
footer {
  background: var(--v-green-main);
  color: rgba(255, 255, 255, 0.85);
}
.footer-brand-text { color: #fff; }
/* V mark is dark green on transparent; white chip keeps it visible on the green footer */
.footer-brand-logo { width: 24px; height: 24px; flex: none; background: #fff; border-radius: 6px; }
.footer-muted { color: rgba(255, 255, 255, 0.5); }
.footer-nav a {
  color: rgba(255, 255, 255, 0.7);
  text-decoration: none;
  transition: color .15s ease;
}
.footer-nav a:hover { color: #fff; }
.footer-legal {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.4);
}
.text-citrus { color: var(--v-citrus) !important; }

.hero {
  background: linear-gradient(135deg, var(--v-green-main), var(--v-green-3));
}

.feature-icon { font-size: 2.5rem; color: var(--v-green-3); }

/* Buttons */
.btn-success { --bs-btn-bg: var(--v-green-2); --bs-btn-border-color: var(--v-green-2);
  --bs-btn-hover-bg: var(--v-green-main); --bs-btn-hover-border-color: var(--v-green-main);
  --bs-btn-active-bg: var(--v-green-main); }
.btn-citrus {
  --bs-btn-color: var(--v-ink); --bs-btn-bg: var(--v-citrus); --bs-btn-border-color: var(--v-citrus);
  --bs-btn-hover-color: var(--v-ink); --bs-btn-hover-bg: #e9a70f; --bs-btn-hover-border-color: #e9a70f;
  --bs-btn-active-bg: #e9a70f; --bs-btn-active-color: var(--v-ink);
}

.code-input { text-transform: uppercase; letter-spacing: .15em; font-weight: 600; }

/* Home code lookup styled as an integrated address bar */
.code-addressbar .code-url-prefix {
  background: var(--v-grey-light);
  color: rgba(24, 21, 22, .55);
  font-family: var(--v-mono);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  border-right: 0;
  padding-right: .1rem;
  white-space: nowrap;
}
.code-addressbar .code-input {
  border-left: 0;
  padding-left: .2rem;
  padding-right: .4rem;
  flex: 0 0 auto;
  width: 7rem;
  min-width: 0;
  /* Same monospace face as the URL prefix so the whole address bar reads as one URL. */
  font-family: var(--v-mono);
}
@media (max-width: 575.98px) {
  /* Reclaim horizontal room so the address bar and the Scan QR button share one
     line on phones instead of Scan QR dropping to its own band. */
  .code-addressbar .code-url-prefix { font-size: .72rem; padding-left: .4rem; }
  .code-addressbar .code-url-prefix .url-proto { display: none; }
  /* Tighter gutter between the address bar and the Scan QR button. */
  .code-lookup-band .row { --bs-gutter-x: .4rem; }
  /* The band's buttons are icon-only here — drop the wide text-button side padding. */
  .code-lookup-band .btn { padding-left: .5rem; padding-right: .5rem; }
}

/* Monospace voucher code in dashboard tables */
.vc-code-cell { font-family: var(--v-mono); letter-spacing: .1em; }

/* Sortable column headers in the voucher tables */
.sort-th { cursor: pointer; user-select: none; white-space: nowrap; }

/* The signature valucher card (public /code view).
   Two panels — the organisation profile (left) and the voucher itself (right) — divided by a
   perforated "tear here" rip line, like a physical ticket stub. The panels stack on mobile and
   the rip turns horizontal. */
.valucher-card { border: none; overflow: hidden; }
.valucher-card .vc-split { display: flex; flex-direction: column; }
.valucher-card .vc-left {
  background: var(--v-grey-light); color: var(--v-ink);
  padding: 1.5rem; flex: 0 0 auto;
}
.valucher-card .vc-right {
  background: var(--v-green-2); color: var(--v-ink);
  padding: 1.5rem; flex: 1 1 auto;
  /* When an org picks a pattern, renderCard() sets background-color + background-image inline;
     the texture tiles over the colour at a tasteful scale. */
  background-repeat: repeat; background-size: 200px;
}
.valucher-card .vc-org-name { font-weight: 700; }
.valucher-card .vc-logo { max-width: 160px; max-height: 90px; object-fit: contain; }
.valucher-card .vc-contact li { margin-bottom: .35rem; }
.valucher-card .vc-contact a { color: inherit; }
.valucher-card .vc-socials { display: flex; gap: .65rem; font-size: 1.35rem; }
.valucher-card .vc-socials a { color: var(--v-green-2); }
.valucher-card .vc-socials a:hover { color: var(--v-green-main); }

/* The rip line — a punched perforation built from the dot_* scallop tiles. The tear is a
   zero-size flex item sitting on the seam between the panels; two pseudo-element rows of white
   half-dots bite into the panel on either side, meeting at the seam to read as punch holes.
   Mobile = panels stacked, so the seam is horizontal (dot_top / dot_bottom, 16×8 tiles). */
.valucher-card .vc-tear {
  position: relative; flex: 0 0 0; height: 0;
  margin: 0 1.25rem;
}
.valucher-card .vc-tear::before,
.valucher-card .vc-tear::after {
  content: ""; position: absolute; left: 0; right: 0; height: 8px;
  background-repeat: repeat-x; background-size: 16px 8px;
}
.valucher-card .vc-tear::before { bottom: 0; background-image: url('/assets/ticket/dot_bottom.png'); }
.valucher-card .vc-tear::after  { top: 0;    background-image: url('/assets/ticket/dot_top.png'); }

@media (min-width: 768px) {
  .valucher-card .vc-split { flex-direction: row; }
  .valucher-card .vc-left { flex: 0 0 34%; }
  /* Side-by-side panels → vertical seam (dot_left / dot_right, 8×16 tiles). */
  .valucher-card .vc-tear {
    align-self: stretch; height: auto; width: 0;
    margin: 1.25rem 0;
  }
  .valucher-card .vc-tear::before,
  .valucher-card .vc-tear::after {
    top: 0; bottom: 0; left: auto; right: auto; height: auto; width: 8px;
    background-repeat: repeat-y; background-size: 8px 16px;
  }
  .valucher-card .vc-tear::before { right: 0; background-image: url('/assets/ticket/dot_left.png'); }
  .valucher-card .vc-tear::after  { left: 0;  background-image: url('/assets/ticket/dot_right.png'); }
}

.valucher-card .vc-code {
  font-family: var(--v-mono);
  letter-spacing: .18em; font-size: 1.4rem; font-weight: 700;
}
.valucher-card .qr { background: #fff; padding: .5rem; border-radius: .5rem; }

/* Right panel layout: QR + code column beside the name/value/progress/For column. */
.valucher-card .vc-grid { display: flex; gap: 1.25rem; align-items: flex-start; }
.valucher-card .vc-qr-col { flex: 0 0 200px; text-align: center; }
.valucher-card .vc-qr-col .qr { width: 100%; height: auto; }
.valucher-card .vc-qr-col .vc-code { font-size: 1rem; letter-spacing: .12em; }
.valucher-card .vc-main-col { flex: 1 1 auto; min-width: 0; }
/* Portrait phones: stack the voucher vertically — QR on top, then name, value,
   progress and issue info full-width below — so the main column isn't squished. */
@media (max-width: 480px) {
  .valucher-card .vc-grid { flex-direction: column; align-items: center; gap: 1rem; }
  .valucher-card .vc-qr-col { flex: 0 0 auto; max-width: 220px; width: 100%; }
  .valucher-card .vc-main-col { width: 100%; }
}
.valucher-card .vc-maps { color: inherit; text-decoration: underline; }
.valucher-card .progress { height: 1.25rem; background: rgba(255,255,255,.45); }
.valucher-card .progress-bar { background-color: var(--v-citrus); color: var(--v-ink); font-weight: 600; }

/* Full-width bands on the public card page (/code/<code>) */
.org-header-band img { display: block; width: 100%; max-height: 260px; object-fit: cover; }
/* Fallback header band (no header image set): a hero-style card-colour surface with
   company_text or the org name, so the band never looks like a blank gap. The background spans
   full width (like the footer band); the text itself is inset to the same column width as the
   card content below it. Colours are set inline per-org. */
.org-header-band-text {
  background: var(--v-green-2); color: var(--v-ink);
  padding: 4rem 1rem;
}
.org-header-band-text p {
  white-space: pre-wrap; font-size: 1.5rem; font-weight: 600; line-height: 1.3;
}
/* Footer matches the card: same default colours as .vc-right, overridden inline per-org. */
.org-footer-band { background: var(--v-green-2); color: var(--v-ink); }
.org-footer-band a { color: inherit; text-decoration: none; }
.org-footer-band a:hover { text-decoration: underline; }
.org-footer-band .band-sep { opacity: .45; margin: 0 .5rem; }
.powered-band { background: var(--v-citrus); color: var(--v-ink); }
.powered-band .fw-semibold { color: var(--v-ink); }

/* Live ticket preview in the Valucher design panel: frames the sample card + bands so the owner
   sees colours, logo and pattern before saving. The QR is a placeholder (no code exists yet). */
.design-preview {
  border: 1px solid rgba(24, 21, 22, .12); border-radius: .5rem;
  background: var(--v-grey-bg); padding: 1rem;
}
.design-preview .org-header-band img { max-height: 140px; }
/* Breathing room above and below the ticket within the preview. */
.design-preview .valucher-card { margin: 1.5rem 0; }

/* Card action bar: right-aligned between ticket and history on desktop, floating bottom-right on mobile */
.card-action-bar {
  display: flex; width: 100%; justify-content: flex-end; flex-wrap: wrap;
  gap: .5rem; margin-top: 2.5rem;
}
.card-action-btn {
  width: 2.75rem; height: 2.75rem; padding: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.15rem;
}
/* Smaller variant for the templates table action column */
.card-action-btn-sm { width: 2.25rem; height: 2.25rem; font-size: 1rem; }
.vc-row-actions { display: inline-flex; flex-wrap: wrap; gap: .4rem; justify-content: flex-end; }
/* Whole "Your cards" rows are clickable — they navigate to the card's /code/<code> view. */
.vc-row-link { cursor: pointer; }
@media (max-width: 768px) {
  .card-action-bar {
    position: fixed; right: 1rem; bottom: 1rem; z-index: 1030;
    width: auto; align-items: flex-end;
    flex-direction: column; flex-wrap: nowrap; gap: .6rem; margin: 0;
  }
  .card-action-btn {
    width: 3.25rem; height: 3.25rem; font-size: 1.3rem;
    box-shadow: 0 .35rem .9rem rgba(0, 0, 0, .35);
  }
}

/* Verified / status badges */
.badge-verified { background: var(--v-green-3); }

/* Date inputs — brand-tinted pickers
   accent-color drives the native calendar popup; the focus ring matches the green buttons;
   the WebKit indicator icon is filtered to brand green so it reads as part of the form. */
input[type="date"] {
  accent-color: var(--v-green-2);
  color-scheme: light;
}
input[type="date"].form-control:focus {
  border-color: var(--v-green-2);
  box-shadow: 0 0 0 .25rem rgba(48, 111, 54, .2);
}
input[type="date"]::-webkit-calendar-picker-indicator {
  /* Shift the default grey icon to --v-green-main */
  filter: invert(22%) sepia(55%) saturate(500%) hue-rotate(98deg) brightness(85%);
  cursor: pointer;
  border-radius: .2rem;
  padding: 2px;
  transition: opacity .15s;
}
input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: .7; }

/* ===== HOMEPAGE — SaaS landing page redesign ===== */

/* Hero — two-column layout; inherits .hero gradient from above */
.hero-badge {
  display: inline-block;
  background: rgba(255,255,255,.18);
  border: 1px solid rgba(255,255,255,.32);
  color: #fff;
  font-size: .82rem;
  font-weight: 700;
  padding: .3rem .9rem;
  border-radius: 2rem;
  letter-spacing: .04em;
  text-transform: uppercase;
}

/* Decorative punch-card mockup shown alongside the hero copy on desktop */
.hero-demo { filter: drop-shadow(0 18px 36px rgba(0,0,0,.38)); }
.hero-demo-label { white-space: nowrap; }
.hero-demo-card {
  border-radius: 1rem;
  overflow: hidden;
  display: flex;
  width: 520px;
  max-width: 100%;
  min-height: 210px;
  background: var(--v-grey-light);
}
.hero-demo-left {
  background: var(--v-grey-light);
  color: var(--v-ink);
  padding: 1.4rem;
  flex: 0 0 38%;
  display: flex;
  flex-direction: column;
  gap: .6rem;
}
.hero-demo-logo {
  width: 50px; height: 50px;
  background: #fff;
  border-radius: .5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  box-sizing: border-box;
  flex-shrink: 0;
}
.hero-demo-logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.hero-demo-org { font-weight: 700; font-size: .875rem; line-height: 1.25; white-space: nowrap; }
.hero-demo-meta { font-size: .72rem; color: #555; line-height: 1.6; white-space: nowrap; }

/* Vertical tear line matching the real card — reuses the same scallop tiles */
.hero-demo-tear {
  flex: 0 0 0; position: relative; width: 0; align-self: stretch;
}
.hero-demo-tear::before,
.hero-demo-tear::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 8px;
  background-repeat: repeat-y; background-size: 8px 16px;
}
.hero-demo-tear::before { right: 0; background-image: url('/assets/ticket/dot_left.png'); }
.hero-demo-tear::after  { left: 0;  background-image: url('/assets/ticket/dot_right.png'); }

.hero-demo-right {
  background: var(--v-green-2);
  color: #fff;
  padding: 1.4rem;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: .75rem;
}
.hero-demo-name { font-weight: 700; font-size: .95rem; }
.hero-demo-value { font-size: .78rem; opacity: .8; margin-top: .15rem; }
.hero-demo-progress {
  background: rgba(255,255,255,.25);
  border-radius: .4rem;
  height: 1rem;
  overflow: hidden;
}
.hero-demo-bar {
  background: var(--v-citrus);
  height: 100%;
  border-radius: .4rem;
  font-size: .6rem;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: .4rem;
  color: var(--v-ink);
  font-weight: 700;
}
.hero-demo-code {
  font-family: var(--v-mono);
  letter-spacing: .18em;
  font-size: .88rem;
  font-weight: 700;
  text-align: center;
  margin-top: .35rem;
}
/* Mirrors the real card's .vc-grid: QR + code in a narrow left column, details filling the rest */
.hero-demo-grid { display: flex; align-items: flex-start; gap: 1rem; }
.hero-demo-qr-col { flex: 0 0 auto; }
.hero-demo-main-col { flex: 1 1 auto; min-width: 0; }
.hero-demo-qr {
  flex-shrink: 0;
  width: 60px; height: 60px;
  background: #fff;
  border-radius: .4rem;
  padding: 4px;
  box-sizing: border-box;
}
.hero-demo-qr img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* Code lookup strip beneath the hero */
.code-lookup-band {
  background: #fff;
  border-bottom: 1px solid rgba(24,21,22,.08);
  box-shadow: 0 2px 8px rgba(24,21,22,.04);
}

/* Small uppercase section labels used as eyebrow text above each h2 */
.section-label {
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--v-green-3);
}

/* Pain points section */
.pain-section { background: var(--v-grey-bg); }
.pain-item, .feat-card {
  background: #fff;
  border: 1px solid rgba(24,21,22,.09);
  border-radius: .75rem;
  padding: 1.5rem;
}
.pain-item-icon { font-size: 1.75rem; color: var(--v-green-3); }
.pain-solve { color: var(--v-green-main); font-size: 1.2rem; }

/* How it works — numbered steps */
.how-section { background: #fff; }
.step-number {
  width: 3rem; height: 3rem;
  border-radius: 50%;
  background: var(--v-green-main);
  color: #fff;
  font-size: 1.2rem;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Features grid */
.feat-section { background: var(--v-grey-bg); }
.feat-card { transition: box-shadow .15s ease; }
.feat-card:hover { box-shadow: 0 4px 16px rgba(24,21,22,.09); }
.feat-card-icon { font-size: 1.9rem; color: var(--v-green-3); }

/* Final CTA band in citrus yellow */
.cta-band {
  background: var(--v-citrus);
  color: var(--v-ink);
}
.cta-band .btn-success {
  --bs-btn-bg: var(--v-green-main);
  --bs-btn-border-color: var(--v-green-main);
  --bs-btn-hover-bg: var(--v-ink);
  --bs-btn-hover-border-color: var(--v-ink);
}

/* PWA "install app" banner — a slim bar pinned to the bottom, shown only to signed-in users on
   installable browsers (or iOS, with manual steps). Sits below modals/toasts in the stacking order. */
.pwa-install-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1030;
  background: #fff;
  border-top: 1px solid var(--v-grey-light);
  box-shadow: 0 -4px 16px rgba(24, 21, 22, .08);
}
.pwa-install-icon {
  border-radius: 9px;
  flex-shrink: 0;
}
.min-w-0 { min-width: 0; }

/* Pre-launch banner: "the site is here, but you can't sign up yet". Sits directly under the
   sticky navbar and scrolls away with the page — it is informational, not an action, so it does
   not deserve permanent screen real estate. Citrus over ink for a launch-y note that reads as
   news rather than as an error (which is what the green/red palette is reserved for). */
.prelaunch-banner {
  background: var(--v-citrus);
  color: var(--v-ink);
  border-bottom: 1px solid rgba(24, 21, 22, .12);
  /* The page content that follows can bleed upward into this bar: a Bootstrap `.row.g-5` sets a
     negative top margin (-1 × the gutter), and where the section wrapping it has no top padding or
     border — the home hero — that margin collapses outward and drags the whole section up over
     whatever precedes it. The navbar never showed it because .sticky-top already gives it a
     z-index; this bar has to say so itself, or the hero's background paints over the citrus while
     the text (painted in a later phase) still shows, leaving the notice unreadable on the hero. */
  position: relative;
  z-index: 1;
}

/* QR scanner (/scan): the camera preview fills a rounded square; an inset frame marks the target
   area. The video is object-fit:cover so it never letterboxes regardless of the camera aspect. */
.scan-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  max-width: 28rem;
  margin: 0 auto;
  border-radius: 18px;
  overflow: hidden;
  background: #181516;
}
.scan-stage #scan-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.scan-frame {
  position: absolute;
  inset: 14%;
  border: 3px solid rgba(255, 255, 255, .9);
  border-radius: 14px;
  box-shadow: 0 0 0 100vmax rgba(24, 21, 22, .35);
  pointer-events: none;
}

/* --- Rapport KPI tiles -------------------------------------------------------
   Each tile stacks its value over a full-width sparkline: the chart fills the
   box and the current value is centred on top of it. */
.rapport-tile-chart {
  position: relative;
  height: 64px;
  margin-top: .25rem;
}
.rapport-spark {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.rapport-tile-value {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: var(--bs-body-color);
  text-shadow: 0 0 6px rgba(255, 255, 255, .85);
  white-space: nowrap;
}
