/* SchedAI tender builder — styled to the SmartConstructAI brand guide:
   Smart Orange #FF7A59, Construct Navy #2D3E50, AI Teal #00A38D,
   Charcoal Slate #334E68 (body), Off-White Shell #F5F8FA (bg), Arial/system sans-serif. */

:root {
  --orange: #FF7A59;
  --navy: #2D3E50;
  --teal: #00A38D;
  --slate: #334E68;
  --shell: #F5F8FA;
  --white: #FFFFFF;
  --border: #DCE3E9;
  --draft-bg: #FFF3EC;
  --draft-text: #B85A2E;
  --confirmed-bg: #E4F6F2;
  --confirmed-text: #06705F;
  --danger: #C0392B;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: Arial, system-ui, -apple-system, sans-serif;
  background: var(--shell);
  color: var(--slate);
  line-height: 1.25;
}

header.app-header {
  background: var(--navy);
  color: var(--white);
  padding: 20px 32px;
  display: flex;
  align-items: baseline;
  gap: 12px;
}
header.app-header .wordmark { font-size: 24px; font-weight: bold; }
header.app-header .wordmark span { color: var(--orange); }
/* Ecosystem logo mark (added 13 Aug 2026) — header uses align-items:baseline for its text
   children, which doesn't suit an image; centre it against the wordmark instead. */
header.app-header .ecosystem-logo { align-self: center; flex-shrink: 0; }
header.app-header .subtitle { font-size: 14px; color: #B7C3CE; }
.account-area { font-size: 14px; display: flex; align-items: center; gap: 10px; }
.account-area button.link-btn { color: #B7C3CE; }
.account-area button.link-btn:hover { color: var(--white); }
/* QA finding, 13 Aug 2026 (Nick): the header's "Pricing" link.link-btn defaults to teal (base
   button.link-btn rule below) but the generic button.link-btn:hover rule turns it navy on hover —
   invisible against this header's own navy background. Scoped override, higher specificity than
   the generic rule, so header links stay visible on hover without touching that rule's intended
   use elsewhere (light-background links like the demo-BoQ trigger). */
header.app-header button.link-btn:hover { color: var(--white); }

/* Round-3 QA follow-up (9 Aug 2026, Nick): 1100px read as a huge, wasted margin on either side of
   real content on a normal monitor — this is a data-dense tool (tables/Gantt), not a prose
   article, so it should use the screen rather than stay pinned to a narrow centred column. Kept
   a generous cap (not truly unbounded) purely so line length stays sane on a 4K/5K display. */
main {
  max-width: 1900px;
  margin: 0 auto;
  padding: 24px 32px 64px;
}

h1 { font-size: 40px; font-weight: bold; color: var(--navy); margin: 0 0 8px; }
h2 { font-size: 28px; font-weight: 600; color: var(--navy); margin: 32px 0 12px; }
h3 { font-size: 20px; font-weight: bold; color: var(--navy); margin: 20px 0 10px; }
h3.tech { color: var(--orange); }
p { font-size: 16px; }

.card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 20px 24px;
  margin-bottom: 20px;
}

button {
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  border: none;
  border-radius: 6px;
  padding: 10px 18px;
  cursor: pointer;
  background: var(--orange);
  color: var(--white);
}
button:hover { filter: brightness(0.92); }
button:disabled { background: #C7CDD3; cursor: not-allowed; }
button.secondary { background: var(--white); color: var(--navy); border: 1px solid var(--border); }
button.teal { background: var(--teal); }
button.small { padding: 6px 12px; font-size: 13px; }
/* Round-3 QA follow-up (9 Aug 2026): the demo-BoQ trigger reads as an inline text link, not a
   peer action to real BoQ upload — deliberately lower visual weight than the primary buttons. */
button.link-btn { background: none; color: var(--teal); border: none; padding: 0; font-weight: 600; font-size: inherit; text-decoration: underline; border-radius: 0; }
button.link-btn:hover { filter: none; color: var(--navy); }

textarea, input[type=text] {
  width: 100%;
  font-family: inherit;
  font-size: 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
  color: var(--slate);
}
textarea { min-height: 120px; resize: vertical; }

/* stage stepper */
.stepper { display: flex; gap: 4px; margin-bottom: 24px; }
.step {
  flex: 1;
  text-align: center;
  padding: 10px 6px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 6px;
  background: var(--white);
  border: 1px solid var(--border);
  color: #94A0AB;
}
.step.done { background: var(--confirmed-bg); color: var(--confirmed-text); border-color: var(--confirmed-bg); }
.step.active { background: var(--navy); color: var(--white); border-color: var(--navy); }

/* "how it works" overview strip (17 Aug 2026) — static, informational only, shown once on the
   upload screen before a conversation exists. Deliberately a different class from .stepper
   above (which tracks a REAL in-progress conversation's 6 stages) so the two are never confused
   in the markup — this one never gets a .done/.active state, it's just a fixed explainer. */
.how-it-works { display: flex; flex-wrap: wrap; gap: 12px; margin: 18px 0 22px; }
.how-it-works .hiw-step {
  flex: 1 1 200px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  position: relative;
}
.how-it-works .hiw-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--navy);
  color: var(--white);
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 8px;
}
.how-it-works .hiw-title { font-weight: 700; color: var(--navy); font-size: 14px; margin-bottom: 4px; }
.how-it-works .hiw-desc { font-size: 12.5px; color: var(--slate); line-height: 1.35; }
.how-it-works-note {
  background: var(--shell);
  border: 1px solid var(--border);
  border-left: 4px solid var(--orange);
  border-radius: 6px;
  padding: 10px 14px;
  font-size: 13px;
  color: var(--slate);
  margin-bottom: 22px;
}

/* activity list */
table.activities { width: 100%; border-collapse: collapse; font-size: 14px; }
table.activities th { text-align: left; color: var(--navy); font-size: 12px; text-transform: uppercase; letter-spacing: 0.03em; padding: 6px 8px; border-bottom: 2px solid var(--border); }
table.activities td { padding: 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.badge { display: inline-block; padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.badge.draft { background: var(--draft-bg); color: var(--draft-text); }
.badge.confirmed { background: var(--confirmed-bg); color: var(--confirmed-text); }
.badge.review { background: #FDECEC; color: var(--danger); }

/* question panel */
.question { border-bottom: 1px solid var(--border); padding: 14px 0; }
.question:last-child { border-bottom: none; }
.question .why { font-size: 13px; color: #6E7C89; margin-top: 4px; }
.question .answer-row { display: flex; gap: 8px; margin-top: 8px; }
.question .answer-row input { flex: 1; }
.answer-recorded { font-size: 13px; margin-top: 6px; padding: 6px 10px; border-radius: 6px; background: var(--shell); }
.answer-recorded.unconfirmed { background: var(--draft-bg); color: var(--draft-text); }
.answer-recorded.confirmed { background: var(--confirmed-bg); color: var(--confirmed-text); }

/* gantt — freeze-pane layout: a fixed (non-scrolling) left column of data cells, and an
   independently horizontally-scrollable, pixel-based, zoomable right column for the timeline.
   Both sides use the exact same GANTT_ROW_H per row (see app.js) so a row in one lines up with
   the same row in the other by construction, not by trusting two separate layouts to agree. */
.gantt-legend { display: flex; gap: 20px; align-items: center; font-size: 13px; color: var(--slate); margin-bottom: 14px; flex-wrap: wrap; }
.gantt-legend .swatch { display: inline-block; width: 12px; height: 12px; border-radius: 2px; margin-right: 6px; vertical-align: -2px; }
.gantt-legend .milestone-swatch { background: var(--navy); transform: rotate(45deg); width: 9px; height: 9px; }
.gantt-zoom { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.gantt-zoom button { padding: 4px 10px; }

.gantt-wrap { display: flex; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.gantt-fixed-col { flex: 0 0 auto; width: 620px; max-width: 55%; border-right: 2px solid var(--border); overflow: hidden; }
.gantt-scroll-col { flex: 1 1 auto; overflow-x: auto; overflow-y: hidden; }

.gantt-fixed-row { display: flex; font-size: 13px; }
.gantt-fixed-row .gc, .gantt-fixed-row .gh { box-sizing: border-box; height: 100%; padding: 0 8px; display: flex; align-items: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-bottom: 1px solid var(--border); }
.gantt-fixed-header { height: 34px; }
.gantt-fixed-header .gh { font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--navy); font-weight: 700; background: var(--shell); border-bottom: 2px solid var(--border); }
.gantt-fixed-row .gc.critical-text { color: var(--orange); font-weight: 700; }
/* Round-3 QA follow-up (9 Aug 2026, Nick): "add text wrapping to a maximum of 2 lines" — first
   for Name, then ID — overrides the shared single-line-ellipsis .gc rule above with a 2-line
   clamp instead (display:-webkit-box + line-clamp is supported in every current-generation
   browser despite the -webkit- prefix). GANTT_ROW_H in app.js was raised to fit two lines for
   every row (not just wrapped ones), since the fixed columns and the timeline bars share one row
   height by construction (see app.js's GANTT_ROW_H comment) — a per-row variable height would
   break bar/milestone/arrow alignment against the timeline on the right; already tall enough
   (42px) for this second wrapped column too, no further row-height change needed. */
.gantt-fixed-row .gc.gcol-name, .gantt-fixed-row .gc.gcol-id {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  white-space: normal;
  line-height: 1.3;
  padding-top: 4px;
  padding-bottom: 4px;
  word-break: break-word;
}
/* Round-3 QA follow-up (9 Aug 2026, Nick): real activity IDs, predecessor strings, and calendar
   names on a live import (SRL-PRFP-M30) were clipping — these were sized for the short synthetic
   test data used while building this, not real 8-11 char P6 activity ids or multi-predecessor
   chains. Widened id/pred/cal/date; wbs bumped slightly too for deeper real WBS coding. */
.gcol-wbs { flex: 0 0 64px; } .gcol-id { flex: 0 0 110px; } .gcol-name { flex: 1 1 auto; min-width: 120px; }
.gcol-dur { flex: 0 0 56px; } .gcol-date { flex: 0 0 96px; } .gcol-pred { flex: 0 0 220px; } .gcol-float { flex: 0 0 70px; }
.gcol-cal { flex: 0 0 140px; }
.milestone-tag { font-size: 10px; color: var(--teal); font-weight: 700; text-transform: uppercase; }

.gantt-timeline-header { height: 34px; border-bottom: 2px solid var(--border); background: var(--shell); position: relative; }
.gantt-timeline-body { position: relative; }
.gantt-axis-track { position: relative; height: 100%; }
.gantt-axis-tick { position: absolute; font-size: 12px; font-weight: 600; color: var(--navy); border-left: 1px solid var(--border); padding-left: 4px; top: 8px; white-space: nowrap; }
.gantt-gridline { position: absolute; top: 0; bottom: 0; border-left: 1px solid var(--border); }
.gantt-bar { position: absolute; border-radius: 4px; min-width: 2px; }
.gantt-bar.critical { background: var(--orange); }
.gantt-bar.float { background: #8FA0AF; }
.gantt-milestone { position: absolute; transform: rotate(45deg); border-radius: 2px; }
.gantt-milestone.critical { background: var(--orange); }
.gantt-milestone.float { background: var(--navy); }
.gantt-arrows { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.gantt-arrow { fill: none; stroke: #94A0AB; stroke-width: 1.4; }
.gantt-arrowhead { fill: #94A0AB; }

/* Item 8 (11 Aug 2026, Nick): current-date and data-date vertical lines through the barchart —
   data date already existed as data (the text caption below the chart, untouched by this), this
   is the actual visual line. Both sit above the gridlines/bars (z-index 3, no explicit z-index on
   those so they default below) but below the logic-arrow SVG overlay (z-index 4, see .gantt-
   arrows' natural DOM-order stacking) so a relationship arrow crossing "today" stays legible.
   pointer-events:none on both — they're informational, not clickable, and shouldn't intercept a
   click meant for the bar underneath. */
.gantt-today-line, .gantt-datadate-line {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 0;
  border-left: 2px dashed var(--teal);
  z-index: 3;
  pointer-events: none;
}
.gantt-datadate-line { border-left-color: var(--navy); }
.gantt-line-label {
  position: absolute;
  top: 2px;
  left: 4px;
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
  padding: 1px 5px;
  border-radius: 3px;
  color: var(--white);
}
.gantt-line-label.today { background: var(--teal); }
.gantt-line-label.datadate {
  background: var(--navy);
  /* Stack below the Today label rather than overlap it, for the (fairly common) case of a
     schedule being viewed close to its own data date. */
  top: 18px;
}

.notice { font-size: 13px; padding: 10px 14px; border-radius: 6px; margin-bottom: 12px; }
.notice.info { background: var(--shell); color: var(--slate); }
.notice.error { background: #FDECEC; color: var(--danger); }
.notice.success { background: var(--confirmed-bg); color: var(--confirmed-text); }

.muted { color: #94A0AB; font-size: 13px; }
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; justify-content: flex-start; }
.spacer { flex: 1; }

.step { cursor: pointer; }
.step.viewing { box-shadow: inset 0 0 0 2px var(--orange); }

.predecessor-picker { border: 1px solid var(--border); border-radius: 6px; padding: 10px; margin-top: 8px; background: var(--shell); }
.predecessor-picker .pred-row { display: flex; gap: 8px; align-items: center; padding: 4px 0; font-size: 13px; }
.predecessor-picker select { font-family: inherit; font-size: 13px; border: 1px solid var(--border); border-radius: 4px; padding: 4px 6px; }
.predecessor-picker input[type=number] { width: 55px; font-size: 13px; border: 1px solid var(--border); border-radius: 4px; padding: 4px 6px; }

.answer-thread { border-left: 3px solid var(--border); padding-left: 10px; margin-top: 8px; }
.answer-scope-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--teal); font-weight: 700; margin-bottom: 3px; }

/* calendar manager — the Y/N weekly spreadsheet + the clickable visual year grid, both real
   views over the same working_days/exceptions data (see app.js's renderCalendarManagerBody).
   Round-3 QA #8 (9 Aug 2026): rebuilt as an actual Mon-Sun aligned table per Nick's request,
   rather than a flex-wrapped row of individually-labelled toggle buttons. */
.cal-weekday-grid { border-collapse: collapse; }
.cal-weekday-grid th, .cal-weekday-grid td { border: 1px solid var(--border); padding: 6px 12px; text-align: center; font-size: 13px; }
.cal-weekday-grid th { background: var(--shell); color: var(--navy); font-weight: 700; }
.cal-day-toggle { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; background: var(--white); border: 1px solid var(--border); border-radius: 6px; padding: 5px 10px; cursor: pointer; }
.cal-year-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.cal-month { font-size: 11px; }
.cal-month-label { font-weight: 700; color: var(--navy); margin-bottom: 4px; }
.cal-month-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cal-day-cell { display: flex; align-items: center; justify-content: center; aspect-ratio: 1; border-radius: 3px; cursor: pointer; background: var(--confirmed-bg); color: var(--confirmed-text); }
.cal-day-cell.off { background: var(--draft-bg); color: var(--draft-text); }
.cal-day-cell.blank { cursor: default; background: none; }
.cal-day-cell.weekday-label { cursor: default; background: none; font-weight: 700; color: var(--slate); aspect-ratio: auto; }
.cal-day-cell.override { box-shadow: inset 0 0 0 1.5px var(--orange); font-weight: 700; }
.cal-day-cell:hover:not(.blank) { filter: brightness(0.92); }

.report-section { margin-bottom: 28px; }
.report-section h3 { border-bottom: 2px solid var(--border); padding-bottom: 6px; }
.report-answer { font-size: 14px; padding: 6px 0; border-bottom: 1px solid var(--border); }
.report-answer .q { color: var(--navy); font-weight: 600; }
.report-answer .a { color: var(--slate); }
.report-answer .scope { font-size: 12px; color: var(--teal); }

@media print {
  .no-print { display: none !important; }
  body { background: var(--white); }
  main { max-width: none; padding: 0 12px; }
  .card { border: none; padding: 6px 0; margin-bottom: 10px; page-break-inside: avoid; }
  button { display: none !important; }
  a[href]:after { content: none !important; }
  /* Printing can't horizontally scroll — let the timeline render at full width instead of
     clipping. A very long or heavily zoomed-in programme may still run off the printed page
     width; zooming out before printing keeps it on one page. */
  .gantt-scroll-col { overflow: visible; }
  .gantt-wrap { overflow: visible; }

  /* Print Barchart button (round-2 #4): prints only the Gantt, not the Activities table or the
     current stage panel that are also on the conversation screen. */
  body.print-barchart-only #activities-card,
  body.print-barchart-only #stage-panel {
    display: none !important;
  }

  /* Round-2 #9: Prepared by/Approved by print header fields read as filled-in text, not an
     editable form control, on the printed page. */
  .print-signoff input {
    border: none;
    background: transparent;
    padding: 0;
    font: inherit;
    color: inherit;
  }

  /* Item 7 (print polish, 11 Aug 2026): Rev box reads as a filled-in title-block field on the
     printed page, same treatment as the Prepared/Approved by fields above — no visible border,
     box, or input chrome, just the value. Kept bold since a revision letter/number is meant to
     stand out on a real title block. */
  .print-rev-box input {
    border: none;
    background: transparent;
    padding: 0;
    font: inherit;
    font-weight: bold;
    color: inherit;
  }
}

/* Item 7 (print polish, 11 Aug 2026): barchart title block — logo, project name, and a Rev box,
   laid out left-to-right the way a printed P6/MSP title block conventionally reads. Shown on
   screen too (not print-only) so what's on screen while typing Prepared by/Approved by/Rev
   matches what prints, rather than only appearing at print time. */
.print-logo {
  flex-shrink: 0;
  margin-top: 2px;
}
.print-rev-box {
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 12px;
  text-align: center;
  min-width: 60px;
}
.print-rev-box-label {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--slate);
  margin-bottom: 2px;
}
.print-rev-box input {
  width: 100%;
  text-align: center;
  border: none;
  font-size: 16px;
  font-weight: bold;
  color: var(--navy);
  padding: 0;
}
.print-rev-box input:focus {
  outline: 1px solid var(--teal);
}

/* "Ask SchedAI" (item 12, 11 Aug 2026) — floating button + chat panel, available on every screen. */
#ask-schedai-btn {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 20;
  background: var(--teal);
  color: var(--white);
  border: none;
  border-radius: 999px;
  padding: 12px 18px;
  font-weight: 600;
  font-size: 14px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
}
#ask-schedai-btn:hover {
  background: #048570;
}
#ask-schedai-btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.25);
  font-size: 12px;
}

#ask-schedai-panel {
  position: fixed;
  right: 20px;
  bottom: 76px;
  z-index: 20;
  width: 360px;
  max-width: calc(100vw - 40px);
  max-height: 70vh;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.22);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.ask-panel-header {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--shell);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  position: relative;
}
.ask-panel-close {
  position: absolute;
  top: 6px;
  right: 8px;
  background: none;
  border: none;
  font-size: 20px;
  line-height: 1;
  color: var(--slate);
  cursor: pointer;
  padding: 4px;
}
#ask-panel-history {
  flex: 1;
  overflow-y: auto;
  padding: 12px 14px;
  min-height: 120px;
}
.ask-msg {
  margin-bottom: 14px;
  font-size: 14px;
  line-height: 1.4;
}
.ask-msg-question {
  font-weight: 600;
  color: var(--navy);
  margin-bottom: 4px;
}
.ask-msg-answer {
  color: var(--slate);
  white-space: pre-wrap;
}
.ask-msg-sources {
  margin-top: 6px;
  font-size: 11px;
  color: var(--slate);
  opacity: 0.75;
}
.ask-msg-error {
  color: var(--danger);
}
.ask-panel-input-row {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--border);
}
.ask-panel-input-row input {
  flex: 1;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
}
.ask-panel-input-row button {
  padding: 8px 14px;
  font-size: 13px;
}
@media print {
  #ask-schedai-btn, #ask-schedai-panel { display: none !important; }
}

/* Popup step instructions (8 Aug 2026 scope note; built 10 Aug 2026) — one small "?" trigger per
   upload-screen option, opening a lightweight modal with that path's own step-by-step walkthrough.
   Kept as one shared modal shell (content swapped per option) rather than one modal per card. */
button.info-btn {
  background: none;
  border: 1.5px solid var(--teal);
  color: var(--teal);
  width: 22px;
  height: 22px;
  min-width: 22px;
  border-radius: 50%;
  padding: 0;
  font-size: 13px;
  font-weight: bold;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  margin-left: 8px;
}
button.info-btn:hover { filter: none; background: var(--teal); color: var(--white); }

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(45, 62, 80, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 20px;
}
.modal-box {
  background: var(--white);
  border-radius: 10px;
  max-width: 560px;
  width: 100%;
  max-height: 85vh;
  overflow-y: auto;
  padding: 24px 26px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
}
.modal-box h3 { margin-top: 0; color: var(--navy); }
.modal-box ol { margin: 0 0 16px; padding-left: 22px; }
.modal-box ol li { margin-bottom: 10px; line-height: 1.4; }
.modal-box ol li strong { color: var(--navy); }
.modal-box .modal-close-row { text-align: right; margin-top: 4px; }

/* Pricing (item 9, 11 Aug 2026) — two-card layout, same visual language as xerScore/SafeSpec's
   existing .pricing-card pattern (border, tier label, big price, feature tagline, featured-card
   accent) but built on SchedAI's own CSS variables rather than a copy-pasted separate stylesheet.
   Where xerScore's cards end in a mailto: CTA, these end in a live <stripe-buy-button> instead —
   the button styling itself is configured inside Stripe's own dashboard (brand colours already
   set to match there), not overridden here. */
.pricing-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(220px, 1fr));
  gap: 16px;
  margin-top: 14px;
}
.pricing-card {
  position: relative;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 20px;
  background: var(--shell);
}
.pricing-card.featured {
  border-color: var(--orange);
  background: var(--white);
  box-shadow: 0 2px 10px rgba(255, 122, 89, 0.12);
}
.pricing-badge {
  position: absolute;
  top: -10px;
  right: 16px;
  background: var(--orange);
  color: var(--white);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 3px 10px;
  border-radius: 999px;
}
.pricing-tier { font-size: 13px; font-weight: 700; color: var(--navy); text-transform: uppercase; letter-spacing: 0.03em; }
.pricing-price { font-size: 30px; font-weight: bold; color: var(--navy); margin: 6px 0 4px; }
.pricing-price span { font-size: 14px; font-weight: 600; color: var(--slate); margin-left: 4px; }
.pricing-tagline { font-size: 13px; color: var(--slate); margin-bottom: 14px; min-height: 34px; }
/* QA finding, 13 Aug 2026 (Nick): promo ribbon moved to sit directly on the buy-button box, then
   redone as a diagonal corner ribbon, then finally matched to a reference mockup Nick supplied —
   a classic "sale sash": solid red band, bold black text, running bottom-left to top-right and
   cleanly cropped flush with the box's rounded corners (not trying to touch the exact corner
   pixels — a generously oversized band that overflow:hidden trims off is what gives that clean
   corner-ribbon look in the reference image). fitPromoRibbons() in app.js sets the real angle from
   each box's measured width/height so the diagonal always runs true regardless of box size.
   position:relative + overflow:hidden + matching border-radius clips the band to this box. */
.pricing-buy-btn { display: flex; position: relative; overflow: hidden; border-radius: 6px; }
.pricing-promo-ribbon {
  position: absolute;
  z-index: 2;
  /* pointer-events:none — the ribbon visually crosses the real Subscribe/Buy button, but clicks
     must still reach the Stripe iframe underneath it, not be swallowed by this overlay. */
  pointer-events: none;
  left: 50%;
  top: 50%;
  width: 160%; /* static fallback — fitPromoRibbons() overrides with the real diagonal length */
  transform: translate(-50%, -50%) rotate(-45deg); /* static fallback — see above */
  /* Solid red / black text, per Nick's reference mockup — high-contrast "sale sash" look, easy to
     read at a glance regardless of what's underneath it. */
  background: #E8241C;
  color: #111111;
  text-align: center;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.02em;
  padding: 5px 0;
  box-shadow: 0 1px 6px rgba(0,0,0,0.3);
}
@media (max-width: 640px) {
  .pricing-grid { grid-template-columns: 1fr; }
}
