:root {
  /* Palette v2: a real primary color (deep green, agricultural/lab-
     instrument register) carries buttons, links, active states, and key
     metrics; gold is a deliberately sparing secondary accent for
     calibration/measurement/premium touches only, not buttons. Contrast
     verified numerically during design (see project notes), not
     eyeballed. */
  --app-bg: #F3F1E8;
  --panel: #FFFFFF;
  --panel-alt: #EDEBE0;
  --ink: #20231F;
  --muted: #62665F;
  --line: #D7D9D2;
  --line-strong: #C3C6BC;

  --accent: #245847;        /* primary green -- buttons, links, active states, key metrics */
  --accent-dark: #183F33;   /* hover/pressed state for the above */
  --accent-soft: #E5EEE9;   /* pale green backgrounds, e.g. success states */

  --gold: #B28A45;          /* sparing: calibration/measurement/premium accents, small icons */
  --gold-text: #7D5E2C;     /* darker variant when gold needs to carry text (contrast) -- tuned to clear WCAG AA (4.5:1) against both --panel and --gold-soft, not just eyeballed */
  --gold-soft: #F3ECDD;

  --good: #245847;          /* whole-grain / pass states reuse the primary green */
  --good-soft: #E5EEE9;
  --bad: #A23C2E;
  --bad-soft: #F3DFDA;

  --ink-panel: #16231D;     /* dark section background (header/footer), deep green-black */
  --shadow-sm: 0 1px 2px rgba(32, 35, 31, 0.06), 0 1px 1px rgba(32, 35, 31, 0.08);
  --shadow-md: 0 2px 10px rgba(32, 35, 31, 0.09), 0 1px 2px rgba(32, 35, 31, 0.06);
  --font-display: 'IBM Plex Mono', ui-monospace, monospace;
  --font-body: 'IBM Plex Sans', system-ui, sans-serif;
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  /* Solid surface, no grid overlay -- the grid-paper texture was reducing
     text legibility against panel content sitting on top of it. */
  background: var(--app-bg);
  color: var(--ink);
  font-family: var(--font-body);
  line-height: 1.55;
}

a { color: var(--accent); }

.page {
  max-width: 1160px;
  margin: 0 auto;
  padding: 32px 28px 64px;
}

/* ---------- corner-bracket motif: echoes the calibration sheet's own
   4 corner markers, used to frame the key panels ---------- */
.frame-corners {
  position: relative;
  padding: 18px;
}
.frame-corners::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(var(--accent), var(--accent)) top left / 16px 2px no-repeat,
    linear-gradient(var(--accent), var(--accent)) top left / 2px 16px no-repeat,
    linear-gradient(var(--accent), var(--accent)) top right / 16px 2px no-repeat,
    linear-gradient(var(--accent), var(--accent)) top right / 2px 16px no-repeat,
    linear-gradient(var(--accent), var(--accent)) bottom left / 16px 2px no-repeat,
    linear-gradient(var(--accent), var(--accent)) bottom left / 2px 16px no-repeat,
    linear-gradient(var(--accent), var(--accent)) bottom right / 16px 2px no-repeat,
    linear-gradient(var(--accent), var(--accent)) bottom right / 2px 16px no-repeat;
}

/* ---------- header ---------- */
.site-header {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 24px;
}
.menu-btn {
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  width: 40px;
  height: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  cursor: pointer;
  flex-shrink: 0;
}
.menu-btn:hover { border-color: var(--accent); }
.menu-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.menu-btn-bar { width: 18px; height: 2px; background: var(--ink); border-radius: 1px; }
.site-wordmark {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-body);
  font-size: 20px;
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
  letter-spacing: -0.01em;
  flex: 1;
}
@media (min-width: 700px) {
  .site-wordmark { flex: 0 0 auto; }
}
.site-wordmark-icon {
  width: 20px;
  height: 20px;
  color: var(--accent);
  flex-shrink: 0;
}
/* Inline nav: hidden by default (mobile keeps the hamburger drawer as
   the only way to reach these links), shown as a horizontal row from
   700px up, where the hamburger button then hides in its place -- these
   are two presentations of one set of links, never both at once. */
.site-nav {
  display: none;
  align-items: center;
  gap: 20px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 14px;
  flex: 1;
}
.site-nav a {
  color: var(--ink);
  text-decoration: none;
}
.site-nav a:hover { color: var(--accent); }
@media (min-width: 700px) {
  .menu-btn { display: none; }
  .site-nav { display: flex; }
}
.auth-status {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-size: 13px;
}
.auth-user-name {
  color: var(--ink);
  font-weight: 600;
  max-width: 16ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tier-chip {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 7px;
  border-radius: 2px;
  background: var(--panel-alt);
  color: var(--muted);
  flex-shrink: 0;
}
/* Paid tiers get the sparing gold accent (a premium/membership touch,
   not a data value, so this doesn't conflict with gold being reserved
   away from metric data elsewhere in the design system). Free stays
   neutral -- there's nothing to celebrate about the default tier. */
.tier-chip-starter,
.tier-chip-professional,
.tier-chip-business {
  background: var(--gold-soft);
  color: var(--gold-text);
}
.btn-small { padding: 7px 12px; font-size: 12px; }

/* ---------- muted header (shared report page) ----------
   The public /report/{token} page is a document sent to someone who may
   not have an account -- drop the hamburger and login/register chrome,
   leaving just the wordmark, so it reads as an authoritative report
   rather than the full app with a signup ad on top. */
body.header-muted .menu-btn,
body.header-muted .site-nav,
body.header-muted .auth-status {
  display: none;
}
body.header-muted .site-wordmark {
  text-align: center;
}

/* ---------- side menu (hamburger drawer) ---------- */
.menu-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(22, 35, 29, 0.5);
  z-index: 200;
  display: flex;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.menu-backdrop.is-open { opacity: 1; }
.side-menu {
  background: var(--panel);
  width: 300px;
  max-width: 85vw;
  height: 100%;
  padding: 20px;
  box-shadow: var(--shadow-md);
  display: flex;
  flex-direction: column;
  position: relative;
  transform: translateX(-100%);
  transition: transform 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
.menu-backdrop.is-open .side-menu { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
  .menu-backdrop, .side-menu { transition: none; }
}
.menu-close-btn {
  position: absolute;
  top: 14px;
  right: 14px;
  background: none;
  border: none;
  font-size: 24px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 4px;
}
.menu-close-btn:hover { color: var(--ink); }
.side-menu-account {
  margin-top: 40px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.btn-block { width: 100%; }
.side-menu-login-hint { text-align: center; margin: 2px 0 0; }
.side-menu-list {
  list-style: none;
  margin: 20px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.side-menu-list a {
  display: block;
  padding: 11px 6px;
  color: var(--ink);
  text-decoration: none;
  font-size: 15px;
  border-radius: 4px;
}
.side-menu-list a:hover { background: var(--panel-alt); color: var(--accent); }
.nav-soon { color: var(--muted); font-size: 0.85em; font-weight: 400; }

/* ---------- hero panel ---------- */
.hero-panel { text-align: center; }
.hero-headline {
  margin: 4px auto 12px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 32px;
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: var(--ink);
  max-width: 30ch;
}
.hero-panel .lede {
  margin: 0 auto 20px;
  color: var(--muted);
  font-size: 16px;
  max-width: 40ch;
}
@media (min-width: 560px) {
  .hero-headline { font-size: 40px; }
}
.hero-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.btn-hero {
  width: auto;
  min-width: 180px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.btn-icon { width: 18px; height: 18px; flex-shrink: 0; }
.sheet-status-hint { text-align: center; }
#first-scan-nudge { text-align: center; margin-top: 4px; }

/* ---------- example section ("what you get") ---------- */
.example-panel { text-align: center; }
.example-eyebrow {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-text);
  margin: 0 0 18px;
}
.example-arrow {
  font-size: 22px;
  color: var(--accent);
  flex-shrink: 0;
}
.example-report {
  background: var(--panel-alt);
  border-radius: 6px;
  padding: 20px 16px;
  text-align: left;
}
.example-metric-grid { margin-bottom: 12px; }
.example-metric-grid:last-child { margin-bottom: 0; }
.example-metric-grid .hero-metric-card,
.example-metric-grid .metric-card { background: var(--panel); }

/* ---------- bare sections: connective homepage content that sits on the
   plain background instead of another bordered/shadowed .panel. Reserve
   .panel for the load-bearing surfaces (scan/results, how-it-works
   report preview) -- wrapping every section identically was flattening
   the page into one long stack of identical boxes. ---------- */
.bare-section {
  padding: 8px 4px 36px;
  text-align: center;
}
.bare-section:last-of-type { padding-bottom: 8px; }

/* ---------- features ---------- */
.feature-list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 26px 32px;
  text-align: left;
}
.feature-item {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.feature-icon {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  color: var(--accent);
  margin-top: 2px;
}
.feature-title {
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 4px;
}
.feature-desc { color: var(--muted); font-size: 13.5px; margin: 0; line-height: 1.5; }
@media (max-width: 760px) {
  .feature-list { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .feature-list { grid-template-columns: 1fr; }
}

/* ---------- who it's for ---------- */
.audience-list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}
.audience-title {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 4px;
}
.audience-desc { color: var(--muted); font-size: 13px; margin: 0; line-height: 1.5; }
@media (max-width: 560px) {
  .audience-list { grid-template-columns: repeat(2, 1fr); text-align: left; }
}

/* ---------- how it works: Capture -> Detect -> Report ---------- */
.how-it-works-panel { text-align: center; }
.how-it-works-flow {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 14px;
  margin-bottom: 16px;
}
.how-it-works-step {
  flex: 1;
  min-width: 0;
  max-width: 300px;
  text-align: left;
}
.how-it-works-step-label {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 10px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.how-it-works-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 2px;
  border: 1.5px solid var(--accent);
  color: var(--accent);
  font-size: 12px;
  flex-shrink: 0;
}
/* Shared fixed-height frame for all three "how it works" step visuals --
   previously each had its own unconstrained (Scan, Analysis) or capped
   (Report) height driven by its own source image's aspect ratio, so a
   0.75-aspect photo, a 0.66-aspect photo, and a 1.53-aspect screenshot
   each rendered at a different height and the row looked mismatched.
   One fixed height + object-fit: cover on the image inside makes all
   three the same size regardless of source aspect ratio. */
.how-it-works-photo-box {
  height: 230px;
  overflow: hidden;
  border-radius: 6px;
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  box-sizing: border-box;
}
.how-it-works-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Step 2 keeps the corner-bracket motif (.frame-corners) and a small
   inset so the brackets read as a viewfinder around the photo rather
   than sitting flush on its edge -- the fixed height above already
   accounts for this padding via box-sizing: border-box, so the outer
   box still matches steps 1 and 3 exactly. */
.how-it-works-frame { padding: 10px; }
.how-it-works-frame .how-it-works-img { border-radius: 2px; }

/* Step 3 links to the real /report/demo page -- styled as a link that
   looks like the other two static steps (no underline, no default link
   color) rather than a generic button or a generic <a>. */
.how-it-works-report-btn {
  display: block;
  text-decoration: none;
  color: inherit;
  border-radius: 6px;
  transition: box-shadow 0.15s ease;
}
.how-it-works-report-btn:hover .report-thumb,
.how-it-works-report-btn:focus-visible .report-thumb {
  box-shadow: var(--shadow-md);
}
.how-it-works-report-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.how-it-works-footnote { margin-top: 4px; max-width: 56ch; margin-left: auto; margin-right: auto; }

/* ---------- step 3 report thumbnail: a real screenshot of the actual
   /demo-report page (see backend/scripts/screenshot_demo_report.py),
   with a faded bottom edge suggesting there's more of the page below,
   and an explicit CTA line since the whole thing is a link to a real
   URL. Height/overflow now come from the shared .how-it-works-photo-box
   above; this class only adds what's specific to step 3. ---------- */
.report-thumb {
  position: relative;
  border-radius: 6px 6px 0 0;
}
.report-thumb-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Left-biased: the report's own content (title, labels) is
     left-aligned with more breathing room on the right (badge, blank
     space), so at narrower viewports where this box's aspect ratio
     tightens, cropping from the right loses far less than cropping
     the left would. */
  object-position: left top;
  display: block;
}
.report-thumb-fade {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 56px;
  background: linear-gradient(to bottom, rgba(255,255,255,0), var(--panel-alt) 85%);
  pointer-events: none;
}
.report-thumb-cta {
  display: block;
  text-align: center;
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--accent);
  background: var(--panel);
  border: 1px solid var(--line);
  border-top: none;
  border-radius: 0 0 6px 6px;
  padding: 9px 12px;
}

@media (max-width: 480px) {
  .how-it-works-flow { flex-direction: column; align-items: stretch; }
  .how-it-works-flow .example-arrow { align-self: center; transform: rotate(90deg); }
  .how-it-works-step { max-width: none; }
}

/* ---------- panels ---------- */
.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: var(--shadow-md);
  padding: 28px 32px 30px;
  margin: 0 auto 22px;
  max-width: 980px;
}
/* Narrower variant for single-column, text/form-heavy pages (the scan
   form, contact form, short placeholder pages) -- these read badly
   stretched to 980px (giant buttons, long input rows, short paragraphs
   floating in wide space), so they get their own moderate measure while
   image/grid/data-heavy panels (how-it-works, features, results,
   reports) use the full 980px to actually fill the wider page. */
.panel-narrow { max-width: 640px; }
.panel-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 12px;
}
.step-tag {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 12px;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 2px;
  padding: 1px 6px;
}
h2 { font-size: 18px; margin: 0; font-weight: 700; }
h3 {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 12px;
}
.panel-copy { color: var(--muted); font-size: 14.5px; margin: 0 0 16px; max-width: 62ch; }
.panel-copy-short { color: var(--muted); font-size: 13px; margin: -6px 0 14px; }

.panel-head-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.panel-head-row h2 { font-size: 17px; margin: 0; font-weight: 700; }

/* ---------- disclosure sections (advanced controls, full details) ---------- */
.advanced-details, .full-details {
  margin: 4px 0 18px;
  text-align: left;
}
.advanced-details summary, .full-details summary {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 13px;
  color: var(--accent);
  cursor: pointer;
  padding: 4px 0;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.advanced-details summary::-webkit-details-marker,
.full-details summary::-webkit-details-marker { display: none; }
.advanced-details summary::before, .full-details summary::before {
  content: '\25B8';
  display: inline-block;
  transition: transform 0.12s ease;
}
.advanced-details[open] summary::before, .full-details[open] summary::before {
  transform: rotate(90deg);
}
.full-details summary {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  border-top: 1px solid var(--line);
  padding-top: 16px;
  width: 100%;
}

/* ---------- calibration sheet preview ---------- */
.sheet-preview { display: flex; justify-content: center; margin-bottom: 18px; }
.sheet-svg { width: 130px; height: auto; }
.sheet-page { fill: #fff; stroke: var(--line); stroke-width: 1.5; }
.sheet-work { fill: var(--ink); opacity: 0.88; }
.sheet-marker rect { fill: var(--accent); }
.sheet-ruler { stroke: var(--muted); stroke-width: 1.5; }

.steps-list {
  margin: 18px 0 4px;
  padding-left: 22px;
  font-size: 13.5px;
  color: var(--muted);
}
.steps-list li { margin-bottom: 10px; line-height: 1.5; }
.steps-list li:last-child { margin-bottom: 0; }
.steps-list strong { color: var(--ink); font-weight: 600; }

/* ---------- /help: How it works (3-step page) ----------
   Each step is its own full-width .panel, laid out as a fixed-width
   visual column + a flexible text column -- reuses the homepage's
   how-it-works-step-num/label (numbering carries real sequence here,
   it's a real process the user follows in order) and the calibration
   sheet SVG / report-thumb components rather than inventing new ones. */
.help-intro { margin: 4px 0 0; color: var(--muted); font-size: 14.5px; line-height: 1.5; max-width: 60ch; }
.help-step-panel .how-it-works-step-label { font-size: 16px; margin-bottom: 18px; }
.help-step-panel .how-it-works-step-num { width: 24px; height: 24px; font-size: 13px; }

.help-step-body {
  display: flex;
  align-items: flex-start;
  gap: 28px;
}
.help-step-text { flex: 1; min-width: 0; }
.help-step-text p { margin: 0 0 12px; line-height: 1.6; color: var(--muted); font-size: 14.5px; }
.help-step-text p:last-of-type { margin-bottom: 16px; }

/* Sub-heading inside step 1 for "spread the sample" -- deliberately not
   its own numbered step (see /help redesign discussion): it's part of
   the same prep action as printing the sheet, just visually broken out
   so it isn't lost inside a paragraph. */
.help-step-subhead {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 13.5px;
  color: var(--ink);
  margin: 4px 0 8px !important;
}

/* Fixed-width visual column, shared across steps 1-2 (sheet diagram,
   photo) so they read as one consistent system. Step 3's report card
   keeps its own wider ratio (matches the homepage's how-it-works-
   photo-box) rather than being squeezed into the same square: the
   report screenshot's content (labels, a short data table) reads as
   "a mostly empty box" when cropped to a square, but reads correctly
   as "a document" at a wider, shorter ratio -- same image, same crop
   bias, just proportioned so its actual content fills the frame. */
.help-step-panel .sheet-preview,
.help-photo-frame.help-photo-frame {
  flex: 0 0 200px;
  width: 200px;
  height: 200px;
  margin: 0;
  border-radius: 6px;
  overflow: hidden;
  box-sizing: border-box;
}
.help-step-panel .sheet-preview { display: flex; align-items: center; justify-content: center; border: 1px solid var(--line); }
.help-step-panel .sheet-svg { width: 110px; }
.help-photo-frame { display: block; border: 1px solid var(--line); box-shadow: var(--shadow-sm); position: relative; text-decoration: none; }
.help-step-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.help-report-link {
  flex-basis: 280px;
  width: 280px;
  height: 190px;
  transition: box-shadow 0.15s ease;
}
.help-report-link .report-thumb-img { object-position: left top; }
.help-report-link:hover, .help-report-link:focus-visible { box-shadow: var(--shadow-md); }
.help-report-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.help-recap-title { font-size: 15px; margin: 0; }
/* Recap list keeps a readable line measure even though its panel is
   now full 980px width to match the step panels above -- otherwise
   short list items stretch edge-to-edge and look sparse. */
#help-view .panel .steps-list { max-width: 640px; }

/* Step 2's Scan button reuses .btn-cta's accent styling (it's the one
   action-worthy button in each step, same as Analyze/Share elsewhere)
   but shouldn't stretch full-width sitting under two sentences of text
   the way it does in the hero's flex row or the full-bleed Analyze CTA. */
.help-step-text .btn-cta { width: auto; }

@media (max-width: 560px) {
  .help-step-body { flex-direction: column; align-items: stretch; }
  .help-step-panel .sheet-preview,
  .help-photo-frame { width: 100%; flex-basis: auto; height: 200px; }
}

/* ---------- buttons / fields ---------- */
.btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0;
  border-radius: 2px;
  border: 1px solid var(--ink);
  background: transparent;
  color: var(--ink);
  padding: 11px 18px;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, opacity 0.12s ease;
}
.btn:hover { background: var(--ink); color: var(--panel); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn:disabled:hover { background: transparent; color: var(--ink); }
.btn-primary { background: var(--ink); color: var(--panel); }
.btn-primary:hover { background: var(--accent); border-color: var(--accent); }
.btn-primary:disabled:hover { background: var(--ink); }

/* CTA buttons: the two actions a regular user actually takes -- Analyze
   and Share -- get the warm accent color so they visually outrank every
   other button on the page, rather than blending in with neutral
   secondary controls. */
.btn-cta {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  width: 100%;
  font-size: 15px;
  padding: 14px 18px;
  font-weight: 600;
}
.btn-cta:hover { background: var(--accent-dark); border-color: var(--accent-dark); }
.btn-cta:disabled { background: var(--line); border-color: var(--line); color: var(--muted); opacity: 1; }
.btn-cta:disabled:hover { background: var(--line); }
.btn-analyze { margin-top: 6px; }

.hint { font-size: 13.5px; color: var(--muted); margin: 10px 0 0; line-height: 1.5; }
.error-hint:not(:empty) { color: var(--bad); }

.controls-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
  margin: 20px 0 20px;
  text-align: left;
}
.field label {
  display: block;
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 6px;
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: 0;
}
select {
  width: 100%;
  font-family: var(--font-body);
  font-size: 14px;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fff;
  color: var(--ink);
}
select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Standard "visually hidden but still in the accessibility tree" pattern
   -- not display:none (which would remove it from keyboard/screen-reader
   navigation and make standardSelect.value meaningless for a11y tools),
   just off-screen. The real select stays the single source of truth
   behind the plain-language cards below. */
.visually-hidden-select {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.standard-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.standard-card {
  text-align: left;
  background: #fff;
  border: 1.5px solid var(--line);
  border-radius: 4px;
  padding: 12px 14px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: var(--font-body);
  transition: border-color 0.12s ease, background 0.12s ease;
}
.standard-card:hover { border-color: var(--accent); }
.standard-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.standard-card.is-selected {
  border-color: var(--accent);
  border-width: 1.5px;
  background: var(--accent-soft);
}
.standard-card-title {
  font-weight: 700;
  font-size: 13.5px;
  color: var(--ink);
}
.standard-card-desc {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.45;
}
@media (max-width: 640px) {
  .standard-cards { grid-template-columns: 1fr; }
}

.broken-ratio-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.broken-ratio-row input[type="number"] {
  width: 70px;
  font-family: var(--font-display);
  font-size: 14px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fff;
  color: var(--ink);
}
.broken-ratio-row input[type="number"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.broken-ratio-unit { color: var(--muted); font-size: 14px; }

/* criteria reference box: shows the actual threshold table for whichever
   grading standard is selected */
.criteria-box {
  background: var(--panel-alt);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 14px 16px;
  margin-bottom: 20px;
}
.criteria-label {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 4px;
}
.criteria-desc { font-size: 13px; color: var(--muted); margin: 0 0 10px; }
.criteria-table-grid {
  display: grid;
  gap: 4px 14px;
  font-size: 12.5px;
  margin-bottom: 4px;
}
.criteria-table-title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin: 10px 0 4px;
}
.criteria-table-title:first-child { margin-top: 0; }
.criteria-row { display: flex; justify-content: space-between; padding: 3px 0; border-bottom: 1px dashed var(--line); }
.criteria-row:last-child { border-bottom: none; }
.criteria-row .name { color: var(--ink); }
.criteria-row .range { font-family: var(--font-display); color: var(--muted); }

/* ---------- upload zone ---------- */
.upload-zone {
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  margin: 4px 0 20px;
  text-align: left;
}

/* ---------- results ---------- */
.loading-state { text-align: center; padding: 40px 0; }
.scanline {
  height: 3px;
  width: 60%;
  margin: 0 auto 16px;
  background: var(--accent);
  animation: sweep 1.3s ease-in-out infinite;
}
@keyframes sweep {
  0% { transform: translateX(-70%); opacity: 0.3; }
  50% { opacity: 1; }
  100% { transform: translateX(70%); opacity: 0.3; }
}
@media (prefers-reduced-motion: reduce) {
  .scanline { animation: none; opacity: 0.7; }
}

.annotated-frame { margin-bottom: 4px; }
.annotated-frame img { width: 100%; display: block; border-radius: 2px; }
.report-photo-frame { position: relative; }
.scan-stamp {
  position: absolute;
  left: 10px;
  bottom: 10px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: #fff;
  background: rgba(22, 35, 29, 0.82); /* --ink-panel, translucent */
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 3px;
  padding: 3px 8px;
  pointer-events: none;
}
.legend-hint { margin-bottom: 22px; }
.dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 3px; vertical-align: middle; }
.dot-good { background: var(--good); }
.dot-bad { background: var(--bad); }

.metric-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
  margin-bottom: 28px;
}
.metric-grid-secondary { margin-bottom: 20px; }
.metric-grid-secondary .metric-card { padding: 9px 12px; }
.metric-grid-secondary .metric-value { font-size: 16px; }

/* Hero stats: avg length / avg width / broken% -- the three numbers a
   regular user should see first, given equal visual weight and set apart
   from the smaller secondary grid below. */
.hero-metric-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-bottom: 12px;
}
.hero-metric-card {
  background: var(--panel);
  border: 1.5px solid var(--ink);
  border-radius: 2px;
  padding: 16px 12px;
  text-align: center;
}
.hero-metric-label {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 12.5px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 8px;
}
.hero-metric-value {
  font-family: var(--font-display);
  font-size: 29px;
  font-weight: 600;
  margin: 0;
  line-height: 1.1;
}
.hero-metric-unit { font-size: 15px; color: var(--muted); font-weight: 400; }
@media (max-width: 480px) {
  .hero-metric-grid { grid-template-columns: 1fr; }
  .hero-metric-value { font-size: 22px; }
}

.metric-card {
  background: var(--panel-alt);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 12px 14px;
}
.metric-label {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 6px;
}
.metric-value {
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  margin: 0;
}
.metric-sub { font-size: 12.5px; color: var(--muted); margin: 2px 0 0; }

.subsection { margin-bottom: 28px; }
.chart-wrap { position: relative; height: 220px; }

/* classification */
.fci-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}
.fci-row:last-child { border-bottom: none; }
.badge {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 11.5px;
  padding: 2px 8px;
  border-radius: 2px;
}
.badge-pass { background: var(--good-soft); color: var(--good); }
.badge-fail { background: var(--bad-soft); color: var(--bad); }
.class-bars { display: flex; flex-direction: column; gap: 8px; }
.class-bar-row { display: grid; grid-template-columns: 90px 1fr 40px; align-items: center; gap: 10px; font-size: 13px; }
.class-bar-track { background: var(--panel-alt); border: 1px solid var(--line); border-radius: 2px; height: 14px; overflow: hidden; }
.class-bar-fill { background: var(--accent); height: 100%; }

/* table */
.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: 2px; }
table { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 560px; }
thead th {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--muted);
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--panel-alt);
  position: sticky;
  top: 0;
}
tbody td { padding: 7px 12px; border-bottom: 1px solid var(--line); }
tbody tr:last-child td { border-bottom: none; }
.status-broken { color: var(--bad); }
.status-whole { color: var(--good); }

.site-footer {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 12px;
  text-align: center;
}
.footer-nav {
  display: flex;
  justify-content: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.footer-nav a {
  color: var(--muted);
  text-decoration: none;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 13px;
}
.footer-nav a:hover { color: var(--accent); }
.footer-nav a.is-active,
.site-nav a.is-active {
  color: var(--accent);
  font-weight: 600;
}
.footer-copy { margin: 0; }

/* ---------- links used inline in auth/report UI ---------- */
.btn-link {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: inherit;
  background: none;
  border: none;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  padding: 0;
}
.btn-link:hover { color: var(--ink); }
.btn-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.btn-secondary {
  background: transparent;
  border: 1px solid var(--accent);
  color: var(--accent);
}
.btn-secondary:hover { background: var(--accent); color: #fff; }

.optional-tag {
  font-family: var(--font-body);
  font-weight: 400;
  color: var(--muted);
  text-transform: none;
  letter-spacing: 0;
}

/* ---------- auth modal ---------- */
/* Belt-and-suspenders: any element using the [hidden] attribute must
   actually hide, even if a more specific class rule elsewhere sets its
   own `display` (which otherwise wins over the browser's default
   [hidden]{display:none} at equal specificity). Bit twice by this exact
   bug (once on .preview-img, once on .modal-backdrop) before adding this
   global rule -- keep it above any single-purpose [hidden] override below. */
[hidden] { display: none !important; }

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(25, 26, 22, 0.55);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 16px;
  overflow-y: auto;
  z-index: 100;
}
.modal {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 28px 24px;
  width: 100%;
  max-width: 420px;
  position: relative;
}
.modal h2 {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 20px;
  margin: 0 0 14px;
}
.modal-close {
  position: absolute;
  top: 14px;
  right: 14px;
  background: none;
  border: none;
  font-size: 22px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 4px;
}
.modal-close:hover { color: var(--ink); }
.modal .field { margin-bottom: 14px; }
.modal .field label {
  display: block;
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 6px;
  font-family: var(--font-body);
  font-weight: 600;
}
.modal input, .modal textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: 14px;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fff;
  color: var(--ink);
}
.modal input:focus-visible, .modal textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.modal .btn-primary { width: 100%; margin-top: 4px; }
.modal-switch { text-align: center; margin-top: 14px; }

/* ---------- share link block: the link is always visible once a report
   exists, not hidden behind a "Share" button that can only silently
   succeed or dead-end into raw unstyled URL text (the previous design).
   Reused both inline after a scan and on the report page itself, so a
   report's *viewer* can also re-share it, not just the person who
   originally ran the scan. ---------- */
.share-link-block {
  background: var(--panel-alt);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 14px 16px;
  margin-bottom: 16px;
}
.share-link-heading {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 8px;
}
.share-link-row {
  display: flex;
  gap: 8px;
}
.share-link-input {
  flex: 1;
  min-width: 0;
  font-family: var(--font-display);
  font-size: 13px;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fff;
  color: var(--ink);
}
.share-link-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.share-copy-btn, .share-native-btn {
  flex-shrink: 0;
  padding: 9px 14px;
}
.share-copy-btn.is-copied {
  background: var(--good);
  border-color: var(--good);
  color: #fff;
}
.share-native-btn { padding: 9px 11px; }
.share-qr-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 12px;
}
.share-qr {
  flex-shrink: 0;
  width: 84px;
  height: 84px;
  padding: 4px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 3px;
}
.share-qr img, .share-qr canvas, .share-qr table { display: block; width: 100% !important; height: 100% !important; }
.share-qr-hint { margin: 0; }

/* ---------- report box (logged-in results) ---------- */
.report-box {
  background: var(--good-soft);
  border: 1px solid var(--good);
  border-radius: 2px;
  padding: 14px 16px;
  margin-bottom: 24px;
}
.report-box-label {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--good);
  margin: 0 0 4px;
}
.report-box-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 10px;
}
.checkbox-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  cursor: pointer;
}
.checkbox-row input[type="checkbox"] { accent-color: var(--accent); }

/* ---------- anonymous report box: same shape as .report-box (saved,
   shareable) but gold instead of green, since it's time-limited rather
   than permanent -- a visual cue that there's a better state available
   (registering), not just a different color for its own sake. ---------- */
.report-box-anon {
  background: var(--gold-soft);
  border-color: var(--gold);
}
.report-box-anon .report-box-label { color: var(--gold-text); }
.report-box-anon-pitch { color: var(--ink); }
.report-box-anon-pitch strong { color: var(--gold-text); }
.report-box-anon .btn-secondary { margin-top: 10px; }

/* ---------- daily-limit-reached box (shown instead of results) ---------- */
.limit-hit-box {
  text-align: center;
  padding: 32px 16px;
}
.limit-hit-text {
  font-size: 14.5px;
  color: var(--muted);
  max-width: 44ch;
  margin: 0 auto 16px;
}

/* ---------- uniformity display within metric grid ----------
   This is the single verdict number a report should read as -- give it
   real visual weight above the equal-weight secondary metric-cards
   around it (grains detected, avg L/W) rather than blending in as one
   more spreadsheet cell. Border + value size intentionally echo
   .hero-metric-card's emphasis, but in gold (the design system's
   sparing accent for premium/calibration touches) rather than ink, to
   read as "the number that matters" without introducing a new color. */
.metric-card.uniformity-card {
  grid-column: span 2;
  border: 1.5px solid var(--gold);
  background: var(--gold-soft);
  padding: 14px 16px;
}
.metric-card.uniformity-card .metric-label { color: var(--gold-text); }
.metric-card.uniformity-card .metric-value {
  font-size: 28px;
  color: var(--ink);
}
.uniformity-band {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 2px;
  margin-top: 6px;
}
.uniformity-band-highly-uniform { background: var(--good-soft); color: var(--good); }
.uniformity-band-uniform { background: var(--good-soft); color: var(--good); }
.uniformity-band-mixed { background: var(--panel); color: var(--gold-text); }
.uniformity-band-highly-mixed { background: var(--bad-soft); color: var(--bad); }
@media (max-width: 480px) {
  .metric-card.uniformity-card .metric-value { font-size: 24px; }
}

@media (max-width: 480px) {
  .site-wordmark { font-size: 17px; }
  .panel { padding: 18px 16px 20px; }
  .auth-status { gap: 6px; }
  .hero-actions { flex-direction: column; }
  .btn-hero { width: 100%; }
}

/* ---------- help view (separate "how to scan" page) ---------- */
#help-view .steps-list { margin-top: 20px; }

/* ---------- pricing view ---------- */
.pricing-head-panel { text-align: center; }
.pricing-head-panel .panel-copy { text-align: center; margin: 0 auto 20px; }
.pricing-head-panel h2 { text-align: left; }
.billing-toggle {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 3px;
  background: var(--panel-alt);
}
.billing-toggle-btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 13.5px;
  border: none;
  background: none;
  color: var(--muted);
  padding: 8px 18px;
  border-radius: 6px;
  cursor: pointer;
}
.billing-toggle-btn.is-active {
  background: var(--panel);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
  font-weight: 600;
}

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
  margin: 0 auto 22px;
  max-width: 1120px;
}
.pricing-grid .panel { max-width: none; margin: 0; }
.pricing-card {
  margin-bottom: 0;
  display: flex;
  flex-direction: column;
  position: relative;
}
.pricing-card-featured { border-color: var(--accent); border-width: 1.5px; }
.pricing-badge {
  position: absolute;
  top: -11px;
  left: 20px;
  background: var(--accent);
  color: #fff;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.02em;
  padding: 3px 10px;
  border-radius: 4px;
}
.pricing-badge-gold { background: var(--gold); }
.pricing-tier-name { font-family: var(--font-body); font-size: 18px; font-weight: 700; margin: 6px 0 2px; }
.pricing-tier-tagline { color: var(--muted); font-size: 13px; margin: 0 0 16px; }
.pricing-price { margin: 0 0 4px; line-height: 1; }
.pricing-price-amount { font-family: var(--font-display); font-size: 30px; font-weight: 600; color: var(--ink); }
.pricing-price-period { color: var(--muted); font-size: 14px; margin-left: 2px; }
.pricing-coming-soon { font-family: var(--font-body); font-size: 19px; font-weight: 700; color: var(--gold-text); }
.pricing-price-note { color: var(--muted); font-size: 12px; margin: 0 0 18px; min-height: 15px; }
.pricing-feature-list {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  flex: 1;
  font-size: 13.5px;
}
.pricing-feature-list li {
  padding: 7px 0;
  border-bottom: 1px dashed var(--line);
}
.pricing-feature-list li:last-child { border-bottom: none; }
.pricing-cta { margin-top: auto; }

.pricing-table { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 480px; }
.pricing-table th, .pricing-table td {
  padding: 9px 12px;
  text-align: center;
  border-bottom: 1px solid var(--line);
}
.pricing-table th:first-child, .pricing-table td:first-child { text-align: left; }
.pricing-table thead th {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--muted);
  background: var(--panel-alt);
}
.pricing-table tbody td:first-child { color: var(--muted); }

@media (max-width: 480px) {
  .pricing-badge { left: 16px; }
}

/* ---------- interest-capture modal ---------- */
#interest-modal-tier { font-weight: 600; color: var(--ink); }

/* ---------- public shared-report view ---------- */
.report-view-eyebrow {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--accent);
  margin: 0 0 6px;
}
.report-view-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.report-view-head h2 {
  font-family: var(--font-display);
  font-size: 22px;
  margin: 0;
}
.report-view-verdict {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 13px;
  padding: 5px 12px;
  border-radius: 2px;
  white-space: nowrap;
}
.report-view-verdict.verdict-pass { background: var(--good-soft); color: var(--good); }
.report-view-verdict.verdict-fail { background: var(--bad-soft); color: var(--bad); }
.report-view-verdict.verdict-neutral { background: var(--accent-soft); color: var(--accent); }

.report-view-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px 20px;
  font-size: 13.5px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.report-view-meta-item .label {
  display: block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--muted);
  margin-bottom: 2px;
}

.report-view-contact {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: 13.5px;
  color: var(--muted);
}
.report-view-contact strong { color: var(--ink); }

/* ---------- print stylesheet: shared report page -> PDF ----------
   Scoped to the report route specifically (body.header-muted, already
   set by showView() only for report-view) so printing from anywhere
   else in the app is unaffected. Cheap middle ground per the brief: no
   server-rendered PDF pipeline, just a clean print layout + the
   browser's own "Save as PDF" print destination. */
.report-print-btn { margin-top: 16px; }
@media print {
  body.header-muted .site-header,
  body.header-muted .site-footer,
  body.header-muted .no-print {
    display: none !important;
  }
  body.header-muted .page {
    max-width: none;
    padding: 0;
  }
  body.header-muted .panel {
    box-shadow: none;
    border: 1px solid #999;
    break-inside: avoid;
  }
  body.header-muted .chart-wrap {
    break-inside: avoid;
  }
}

/* ---------- toast: single shared confirmation, used where there's no
   nearby element whose own state change is enough (see showToast() in
   app.js). Bottom-center, auto-dismisses -- not a persistent element. ---------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%) translateY(0);
  background: var(--ink-panel);
  color: #fff;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  padding: 11px 20px;
  border-radius: 4px;
  box-shadow: var(--shadow-md);
  z-index: 400;
  max-width: min(90vw, 420px);
  text-align: center;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.toast[hidden] {
  display: block; /* keep in the transition, not display:none, so fade-out can run */
  opacity: 0;
  transform: translateX(-50%) translateY(8px);
  pointer-events: none;
}
.toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ---------- lightbox: single shared full-photo viewer, used by the scan
   preview and both annotated-photo thumbnails (see openLightbox() in
   app.js). Deliberately simpler than the auth/menu modals -- no inner
   card, just the photo -- since the photo itself is the whole point. ---------- */
.lightbox-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(10, 12, 10, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  z-index: 300;
}
.lightbox-img {
  max-width: 90vw;
  max-height: 90vh;
  object-fit: contain;
  border-radius: 2px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
}
.lightbox-close {
  position: absolute;
  top: 18px;
  right: 20px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox-close:hover { background: rgba(255, 255, 255, 0.22); }
.lightbox-close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* ---------- photo thumbnails: fixed-height, clickable, framed preview
   used for the scan preview and both annotated-photo displays -- these
   used to render at full width with no height cap, which at the wider
   980px panel produced a ~1300px-tall block for a portrait A4 photo. ---------- */
.photo-thumb {
  display: block;
  position: relative;
  background: var(--panel-alt);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 10px;
  cursor: pointer;
  text-align: center;
  width: 100%;
}
.photo-thumb:hover { border-color: var(--accent); }
.photo-thumb:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.photo-thumb img.photo-thumb-img {
  max-height: 220px;
  max-width: 100%;
  width: auto;
  object-fit: contain;
  display: block;
  margin: 0 auto;
  border-radius: 2px;
}
.photo-thumb-zoom-tag {
  position: absolute;
  right: 18px;
  bottom: 18px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  background: rgba(22, 35, 29, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 3px;
  padding: 3px 8px;
  pointer-events: none;
}
.photo-thumb-caption { margin-top: 8px; }

/* Cashfree Subscriptions inline checkout target -- min-height reserves
   space before the iframe/content actually loads into it, so the modal
   doesn't visibly jump from collapsed to full size. Width intentionally
   left to the modal's own max-width (420px, see .modal above), which is
   close enough to Cashfree's own reference sizing (425px) not to warrant
   overriding the modal's standard width just for this one case. */
#cf-checkout-container {
  min-height: 420px;
  width: 100%;
}
