/*
  The public design system: landing, marketplace, product page, pricing, policy pages.

  Written as its own small stylesheet rather than as additions to the BizPage template the old
  landing page was built on. That template carries section styles, animation libraries and carousel
  CSS for a layout none of these pages use, and overriding it produces a page mostly fighting
  itself.

  BRAND
  -----
  The previous revision of this file used a stock SaaS blue (#1b64f2) for every action, eyebrow and
  icon. The logo is a crimson wordmark with amber rays (assets/img/logo_.png, icon.png), and the
  older stylesheet the back office still ships (assets/css/style.min.css) has been using #96110d and
  #ffc325 for years. So the page was competing with its own logo, and the whole thing could have
  belonged to any product. The palette below is taken from the logo:

    --brand   #96110d   crimson, from the wordmark. Actions and nothing else.
    --accent  #ffc325   amber, from the rays. Highlights, motifs, marks on dark. Never a text
                        colour on light, and never a button fill behind white text.

  Both are checked: white on --brand is 8.8:1, --ink on --accent is 10.8:1, --ink-soft on white is
  6.7:1. The ray motif itself is reused as a background graphic (.ray-field) rather than as more
  decoration invented for this page.

  THE GREY-ON-BLUE BUG
  --------------------
  `.nav-links > a` (0,1,1) outranked `.btn-primary` (0,1,0), so any button placed in the navigation
  took the navigation's muted link colour: the "Get started" call to action rendered #5a6b7d text on
  #1b64f2, a contrast ratio of 1.08:1 - effectively invisible. It was not a problem with that
  button, it was a container rule claiming descendants it does not own. Fixed at the source: the
  navigation colours `> a:not(.btn)`, so a component dropped into the bar keeps its own identity.
  The same `:not(.btn)` discipline is applied to every other container that colours links.

  RULES FOLLOWED
  --------------
    - one accent, one brand colour, used for meaning rather than decoration;
    - every interactive element has hover, focus-visible, active and disabled states;
    - motion is opt-out via prefers-reduced-motion, and never gates content or navigation.
*/

/* ================================================================== tokens */

/*
  These names are this stylesheet's own vocabulary, kept so the ~800 lines below did not have to be
  rewritten. Each one now READS the canonical token published by resources/css/app.css (built from
  tailwind.config.js) rather than declaring a second copy of the value, so there is one place to
  change a colour and the public pages and the application cannot drift apart.

  The literal after the comma is a fallback, not a duplicate source of truth: if the built
  stylesheet is ever missing, the public pages degrade to the correct palette instead of losing
  every colour at once. Keep the fallbacks equal to the tokens.
*/
:root {
  /* Ink is warm rather than blue-grey, so it sits with the crimson instead of against it. */
  --ink: var(--text-primary, #1d1917);
  --ink-soft: var(--text-secondary, #645a56);
  /* Was #8c817c, which measured 3.52:1 on --surface-alt and 3.79:1 on white - under the 4.5:1
     minimum for the small labels it is used on (meta lines, answer weights, the footer's payment
     note). #756a65 keeps the same "quieter than body copy" role at 4.88:1 and 5.24:1. */
  --ink-faint: var(--text-muted, #756a65);

  --brand: var(--brand-primary, #96110d);
  --brand-deep: var(--brand-primary-hover, #7a0d0a);
  /* --brand-tint and --brand-line are published by app.css under these exact names. */

  --accent: var(--brand-accent, #ffc325);
  --accent-deep: var(--brand-accent-hover, #d99f0c);

  --surface: var(--surface-page, #ffffff);
  --surface-alt: var(--surface-subtle, #faf6f3);
  --surface-ink: var(--surface-emphasis, #241d1b);

  --line: var(--border-default, #e7e0dc);
  --line-strong: var(--border-strong, #d3c8c2);

  /* Public pages keep a slightly softer radius than the application, which is the one deliberate
     difference between the two densities. */
  --radius: 10px;
  --radius-lg: 16px;
  --shell: var(--width-editorial, 1140px);

  --shadow-sm: 0 1px 2px rgba(29, 25, 23, .05);
  --shadow-md: 0 12px 28px -20px rgba(29, 25, 23, .45);
  --shadow-lg: 0 26px 60px -34px rgba(29, 25, 23, .55);
}

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

/*
  The header is sticky, so an in-page jump ("Product" -> #product) parks the section's heading
  underneath it and the reader arrives mid-paragraph. scroll-margin gives every anchor target the
  header's height back; the smooth behaviour is turned off again for anyone who asked for reduced
  motion, at the bottom of this file.
*/
html { scroll-behavior: smooth; }
section[id], [id]:target { scroll-margin-top: 88px; }

body {
  margin: 0;
  font-family: Inter, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  color: var(--ink);
  background: var(--surface);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.container { width: 100%; max-width: var(--shell); margin: 0 auto; padding: 0 20px; }

/* ============================================================ typography */

/* Titles come from publishers, so a single long word ("Internationalization" at heading size) has
   to break rather than push the page sideways on a narrow screen. */
h1, h2, h3, h4 { color: var(--ink); font-weight: 700; letter-spacing: -0.021em; line-height: 1.15; margin: 0 0 .5rem; overflow-wrap: break-word; }
p { margin: 0 0 1rem; }

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

/* A visible focus ring everywhere. Removing outlines without replacing them is the single most
   common accessibility regression in a redesign. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.btn:focus-visible,
summary:focus-visible {
  outline: 3px solid rgba(150, 17, 13, .40);
  outline-offset: 2px;
  border-radius: 4px;
}
/* On dark ground the crimson ring disappears into the background; amber is the readable one. */
.on-dark a:focus-visible,
.on-dark button:focus-visible,
.on-dark .btn:focus-visible {
  outline-color: rgba(255, 195, 37, .75);
}

/* .skip-link moved to resources/css/app.css with the header it belongs to. */

/* The eyebrow carries the brand at small sizes, which is most of where a brand actually lives. */
.eyebrow {
  display: inline-flex; align-items: center; gap: .5rem;
  text-transform: uppercase; letter-spacing: .11em; font-size: .72rem; font-weight: 700;
  color: var(--brand); margin-bottom: .7rem;
}
.eyebrow::before { content: ""; width: 18px; height: 2px; background: var(--accent); border-radius: 2px; }
.on-dark .eyebrow { color: var(--accent); }
.on-dark .eyebrow::before { background: var(--accent); }

/* ================================================================ buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-weight: 600; font-size: .95rem; line-height: 1.2;
  border-radius: 8px; padding: .72rem 1.25rem; border: 1px solid transparent;
  cursor: pointer; text-align: center;
  transition: background-color var(--speed) var(--ease), border-color var(--speed) var(--ease),
              color var(--speed) var(--ease), box-shadow var(--speed) var(--ease),
              transform var(--speed) var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
/* Disabled reads as inert through the flat fill, the missing shadow and the cursor - not by making
   the label unreadable, which is the usual way this state is done. */
.btn[disabled], .btn.disabled, .btn:disabled {
  opacity: 1; cursor: not-allowed; pointer-events: none;
  background: #eee9e6; border-color: #ded7d3; color: #6f6560; box-shadow: none; transform: none;
}

.btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; box-shadow: var(--shadow-sm); }
.btn-primary:hover, .btn-primary:focus { background: var(--brand-deep); border-color: var(--brand-deep); color: #fff; box-shadow: var(--shadow-md); }

/* Bootstrap ships .btn-outline-dark and the marketplace pages already use it, so it stays the name
   of the secondary button rather than becoming a second vocabulary for the same thing. */
.btn-outline-dark { background: var(--surface); border-color: var(--line-strong); color: var(--ink); }
.btn-outline-dark:hover, .btn-outline-dark:focus { border-color: var(--ink); background: var(--surface); color: var(--ink); box-shadow: var(--shadow-md); }

.btn-ghost { background: transparent; border-color: transparent; color: var(--brand); padding-inline: .35rem; }
.btn-ghost:hover { color: var(--brand-deep); text-decoration: underline; }

.btn-lg { padding: .9rem 1.7rem; font-size: 1.02rem; border-radius: 9px; }
.btn-sm { padding: .5rem .95rem; font-size: .88rem; }
.btn-block { display: flex; width: 100%; }

/* On a dark ground the outline button needs its own colours, not an override per section. */
.on-dark .btn-outline-dark { background: transparent; border-color: rgba(255,255,255,.4); color: #fff; }
.on-dark .btn-outline-dark:hover { border-color: #fff; background: rgba(255,255,255,.08); color: #fff; }

/* A link that has to read as an action without being a button. */
.text-link { color: var(--brand); font-weight: 600; display: inline-flex; align-items: center; gap: .4rem; }
.text-link i { font-size: .8em; transition: transform var(--speed) var(--ease); }
.text-link:hover i { transform: translateX(3px); }

/* The header, the skip link and their responsive rules moved to resources/css/app.css: they are
   shared with _layouts/backoffice, which serves public publisher and result pages and does not load
   this file. See the note above .site-header there. */

/* =============================================================== sections */

.section { padding: 5rem 0; }
.section--tight { padding: 3.25rem 0; }
.section--alt { background: var(--surface-alt); border-block: 1px solid var(--line); }
.section--ink { background: var(--surface-ink); color: #ffffff; }
.section--ink h2, .section--ink h3 { color: #fff; }

.section-head { max-width: 660px; margin-bottom: 2.75rem; }
.section-head h2 { font-size: clamp(1.75rem, 1.2rem + 1.6vw, 2.3rem); }
.section-head p { color: var(--ink-soft); margin: 0; font-size: 1.02rem; }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head--center .eyebrow { justify-content: center; }
.on-dark .section-head p, .section--ink .section-head p { color: #cdbfb9; }

/* A heading row that carries an action on the right and stacks cleanly when it cannot. */
.section-head-row {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 2rem; max-width: none; margin-bottom: 2.25rem; flex-wrap: wrap;
}
.section-head-row .section-head { margin-bottom: 0; }

/* The ray motif from the logo mark, used as ground rather than as another picture. Two soft washes
   plus the fan of lines that the icon is made of. */
.ray-field { position: relative; overflow: hidden; isolation: isolate; }
.ray-field::before {
  content: ""; position: absolute; z-index: -1; inset: -30% -10% auto -35%; height: 150%;
  background:
    radial-gradient(46rem 30rem at 8% 12%, rgba(255, 195, 37, .20), transparent 62%),
    radial-gradient(38rem 26rem at 92% 4%, rgba(150, 17, 13, .10), transparent 60%);
  pointer-events: none;
}
.ray-field::after {
  content: ""; position: absolute; z-index: -1; right: -6rem; top: -4rem; width: 30rem; height: 30rem;
  background: conic-gradient(from 205deg at 0% 50%,
      rgba(255,195,37,.30) 0deg, rgba(255,195,37,0) 12deg,
      rgba(255,195,37,.24) 20deg, rgba(255,195,37,0) 31deg,
      rgba(255,195,37,.18) 39deg, rgba(255,195,37,0) 50deg, transparent 360deg);
  pointer-events: none;
}

/* ================================================================== hero */

.hero { padding: 4.75rem 0 4.25rem; }
.hero-grid { display: grid; grid-template-columns: 1.02fr .98fr; gap: 3.5rem; align-items: center; }
.hero h1 { font-size: clamp(2.15rem, 1.35rem + 2.7vw, 3.25rem); margin-bottom: 1.1rem; }
/* The one phrase the page is built around gets the brand's own underline rather than a colour swap,
   which would fight the headline for weight. */
.hero h1 mark {
  background: linear-gradient(transparent 62%, rgba(255, 195, 37, .55) 62%);
  color: inherit; padding: 0 .1em;
}
.hero .lede { font-size: 1.12rem; color: var(--ink-soft); max-width: 35rem; }
.hero-actions { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 1.9rem; align-items: center; }
.hero-note { margin-top: 1.15rem; font-size: .86rem; color: var(--ink-soft); }

/* Factual reassurance strip. Only things the platform actually does go in here. */
.hero-trust { display: flex; align-items: center; gap: 1.5rem 2rem; flex-wrap: wrap; margin-top: 2.25rem; padding-top: 1.5rem; border-top: 1px solid var(--line); }
.hero-trust__item { display: inline-flex; align-items: center; gap: .5rem; font-size: .85rem; color: var(--ink-soft); }
.hero-trust__item i { color: var(--brand); }
.hero-trust img { height: 19px; width: auto; opacity: .72; }

/* ==================================================== product UI mockups */

/*
  These are the product, drawn in the page's own markup: a browser-ish frame with real assessment
  content inside it. Built rather than photographed so the page stays sharp on every display, weighs
  nothing, and stays truthful - the numbers and wording come from the templates in
  App\Support\Assessments\TemplateLibrary that a new author actually gets.
*/
.ui-frame {
  background: var(--surface); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--shadow-lg); overflow: hidden;
}
.ui-frame__bar {
  display: flex; align-items: center; gap: .5rem; padding: .6rem .85rem;
  border-bottom: 1px solid var(--line); background: var(--surface-alt);
}
.ui-frame__dots { display: flex; gap: .3rem; }
.ui-frame__dots span { width: 9px; height: 9px; border-radius: 50%; background: #d9cfca; }
.ui-frame__label { font-size: .74rem; color: var(--ink-faint); font-weight: 500; letter-spacing: .01em; }
.ui-frame__body { padding: 1.25rem; }

.ui-title { font-weight: 700; font-size: 1.02rem; margin-bottom: .1rem; }
.ui-sub { font-size: .78rem; color: var(--ink-faint); margin-bottom: 1.1rem; }

/* A headline score, so the result reads as a verdict rather than a chart. */
.score-badge { display: flex; align-items: baseline; gap: .55rem; margin-bottom: 1.1rem; }
.score-badge__value { font-size: 2.5rem; font-weight: 700; letter-spacing: -.03em; line-height: 1; color: var(--brand); }
.score-badge__unit { font-size: 1rem; font-weight: 700; color: var(--brand); }
.score-badge__label { font-size: .8rem; color: var(--ink-soft); }

.meter { margin-bottom: .85rem; }
.meter__row { display: flex; justify-content: space-between; gap: 1rem; font-size: .82rem; margin-bottom: .3rem; }
.meter__row span:first-child { color: var(--ink); font-weight: 500; }
.meter__row span:last-child { color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.meter__track { height: 8px; background: #efe8e4; border-radius: 4px; overflow: hidden; }
.meter__fill { height: 100%; background: var(--brand); border-radius: 4px; }
/* Amber marks the dimension that needs attention - the accent doing a job, not decorating. */
.meter__fill--flag { background: var(--accent); }

.ui-verdict {
  margin: 1.1rem 0 0; padding: .85rem .95rem; border-radius: 8px;
  background: var(--brand-tint); border-left: 3px solid var(--brand);
  font-size: .84rem; color: var(--ink); line-height: 1.55;
}
.ui-verdict strong { display: block; font-size: .7rem; text-transform: uppercase; letter-spacing: .09em; color: var(--brand); margin-bottom: .25rem; }

/* A question as the author configures it: answers carrying weights. */
.ui-question { border: 1px solid var(--line); border-radius: 10px; padding: .95rem 1rem; background: var(--surface); }
.ui-question__label { font-weight: 600; font-size: .92rem; margin-bottom: .7rem; }
.ui-answer { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .45rem .6rem; border-radius: 6px; font-size: .86rem; color: var(--ink-soft); }
.ui-answer + .ui-answer { margin-top: .2rem; }
.ui-answer__dot { width: 13px; height: 13px; border-radius: 50%; border: 2px solid var(--line-strong); flex: none; }
.ui-answer__text { flex: 1; }
.ui-answer__weight { font-size: .74rem; font-weight: 700; color: var(--ink-faint); background: var(--surface-alt); border: 1px solid var(--line); border-radius: 20px; padding: .05rem .5rem; font-variant-numeric: tabular-nums; }
.ui-answer--picked { background: var(--brand-tint); color: var(--ink); }
.ui-answer--picked .ui-answer__dot { border-color: var(--brand); background: var(--brand); box-shadow: inset 0 0 0 2px #fff; }
.ui-answer--picked .ui-answer__weight { color: var(--brand); background: #fff; border-color: var(--brand-line); }

/* The three-panel "how it works" band: each step shows the actual screen, not an icon. */
.flow { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.75rem; align-items: start; }
.flow__step { display: flex; flex-direction: column; gap: 1rem; }
.flow__num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  background: var(--brand); color: #fff; font-size: .78rem; font-weight: 700;
}
.flow__head { display: flex; align-items: center; gap: .65rem; }
.flow__head h3 { font-size: 1.05rem; margin: 0; }
.flow__step > p { font-size: .92rem; color: var(--ink-soft); margin: 0; }
.flow__visual { margin-top: auto; }

/* ============================================================= templates */

/*
  Real starting points, read from TemplateLibrary. A visitor sees the subject matter the product is
  actually used for instead of being told there are "templates".
*/
/* Six templates in a three-column track reads as two even rows; auto-fit gave four then a ragged
   two, which looks like something failed to load. */
.template-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.template-card {
  border: 1px solid var(--line); border-radius: var(--radius); padding: 1.15rem 1.2rem;
  background: var(--surface); display: flex; flex-direction: column; gap: .4rem;
  transition: border-color var(--speed) var(--ease), transform var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}
.template-card:hover { border-color: var(--line-strong); transform: translateY(-2px); box-shadow: var(--shadow-md); }
.template-card i { color: var(--brand); font-size: 1.05rem; }
.template-card h3 { font-size: .98rem; margin: .15rem 0 0; }
.template-card p { font-size: .86rem; color: var(--ink-soft); margin: 0; }
.template-card__dims { margin-top: .5rem; display: flex; flex-wrap: wrap; gap: .3rem; }

.chip {
  display: inline-block; font-size: .74rem; font-weight: 500; color: var(--ink-soft);
  background: var(--surface-alt); border: 1px solid var(--line); border-radius: 20px; padding: .12rem .6rem;
}
.chip--accent { background: rgba(255,195,37,.18); border-color: rgba(217,159,12,.35); color: #6b4e05; font-weight: 600; }

/* ============================================================== audience */

.audience-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.75rem; }
.audience {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 1.9rem; position: relative; overflow: hidden;
}
/* One amber hairline at the top edge: enough to tie the cards to the mark without decorating them. */
.audience::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 3px; background: linear-gradient(90deg, var(--brand), var(--accent)); }
.audience h3 { font-size: 1.22rem; }
.audience > p { color: var(--ink-soft); font-size: .96rem; }
.audience ul { list-style: none; margin: 1.15rem 0 0; padding: 0; }
.audience li { position: relative; padding-left: 1.6rem; margin-bottom: .6rem; color: var(--ink-soft); font-size: .94rem; }
.audience li::before {
  content: "\f00c"; font-family: "Font Awesome 5 Free"; font-weight: 900;
  position: absolute; left: 0; top: .12rem; color: var(--brand); font-size: .76rem;
}
.audience li strong { color: var(--ink); font-weight: 600; }

/* ========================================================== capabilities */

.capabilities { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.9rem 2.25rem; }
.capability h3 { font-size: 1rem; margin-bottom: .3rem; }
.capability p { font-size: .9rem; color: var(--ink-soft); margin: 0; }
.capability i {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 9px; margin-bottom: .75rem; font-size: .95rem;
  background: var(--brand-tint); color: var(--brand);
}
.section--ink .capability p { color: #cdbfb9; }
.section--ink .capability i { background: rgba(255,195,37,.14); color: var(--accent); }

/* ========================================================= listing cards */

.listing-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(276px, 1fr)); gap: 1.5rem; }
/*
  A catalogue at pilot scale has a handful of listings, and `auto-fill` stranded a single card in a
  four-column track with three empty columns beside it - which reads as a broken section rather than
  a young one. With fewer than three, the row centres and the cards take a readable width instead.
*/
.listing-grid--few { grid-template-columns: repeat(auto-fit, minmax(276px, 340px)); justify-content: center; }

.listing {
  display: flex; flex-direction: column; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden;
  transition: transform var(--speed) var(--ease), box-shadow var(--speed) var(--ease), border-color var(--speed) var(--ease);
}
.listing:hover, .listing:focus-within { transform: translateY(-3px); border-color: var(--line-strong); box-shadow: var(--shadow-lg); }
.listing__media {
  height: 146px; position: relative; overflow: hidden;
  background: linear-gradient(135deg, var(--brand) 0%, #4a1512 55%, var(--surface-ink) 100%);
  background-size: cover; background-position: center;
  transition: transform 320ms var(--ease);
}
.listing:hover .listing__media { transform: scale(1.03); }
/* When a listing has no cover the gradient alone is flat, so the mark's rays stand in for one. */
.listing__media--blank::after {
  content: ""; position: absolute; inset: 0;
  background: conic-gradient(from 200deg at 12% 50%,
      rgba(255,195,37,.55) 0deg, rgba(255,195,37,0) 9deg,
      rgba(255,195,37,.45) 16deg, rgba(255,195,37,0) 25deg,
      rgba(255,195,37,.35) 32deg, rgba(255,195,37,0) 41deg, transparent 360deg);
}
.listing__badge {
  position: absolute; top: .7rem; right: .7rem; z-index: 1;
  background: #fff; color: var(--ink); font-size: .75rem; font-weight: 700;
  padding: .22rem .6rem; border-radius: 20px; box-shadow: var(--shadow-sm);
}
.listing__badge--free { background: var(--accent); color: var(--ink); }
.listing__body { padding: 1.15rem; display: flex; flex-direction: column; flex: 1; }
.listing__title { font-size: 1.04rem; font-weight: 600; margin-bottom: .35rem; line-height: 1.3; }
.listing__title a { color: var(--ink); }
.listing__title a:hover { color: var(--brand); text-decoration: none; }
/* The whole card is the hit target; the title link is still the accessible name. */
.listing__title a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.listing { position: relative; }
.listing__summary { font-size: .89rem; color: var(--ink-soft); margin-bottom: 1rem; }
.listing__meta {
  margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  font-size: .83rem; color: var(--ink-soft); border-top: 1px solid var(--line); padding-top: .8rem;
}
.listing__publisher { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Publisher links sit above the card-wide overlay so they stay independently clickable. */
.listing__publisher a { position: relative; z-index: 2; color: var(--ink-soft); font-weight: 600; }
.listing__publisher a:hover { color: var(--brand); }
.listing__cta { font-weight: 600; color: var(--brand); white-space: nowrap; display: inline-flex; align-items: center; gap: .35rem; }
.listing__cta i { transition: transform var(--speed) var(--ease); font-size: .78em; }
.listing:hover .listing__cta i { transform: translateX(3px); }

.listing__rating { margin: 0 0 .5rem; }

.empty-state { border: 1px dashed var(--line-strong); border-radius: var(--radius-lg); padding: 3rem 1.5rem; text-align: center; color: var(--ink-soft); background: var(--surface); }

/* ========================================================= product page */

/* `min-width: 0` because a grid item defaults to min-content width: without it the long assessment
   title above set the track wider than the viewport and the whole product page scrolled sideways. */
.listing-hero { display: grid; grid-template-columns: 1.4fr .6fr; gap: 3rem; align-items: start; }
.listing-hero > * { min-width: 0; }
.buy-box { border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 1.6rem; position: sticky; top: 92px; background: var(--surface); box-shadow: var(--shadow-md); }
.buy-box__price { font-size: 2.1rem; font-weight: 700; letter-spacing: -.03em; margin-bottom: .15rem; }
.buy-box__note { font-size: .84rem; color: var(--ink-soft); }
.facts { list-style: none; padding: 0; margin: 1.25rem 0 0; font-size: .9rem; }
.facts li { display: flex; justify-content: space-between; gap: 1rem; padding: .5rem 0; border-top: 1px solid var(--line); color: var(--ink-soft); }
.tag { display: inline-block; background: var(--surface-alt); border: 1px solid var(--line); border-radius: 20px; padding: .2rem .75rem; font-size: .8rem; color: var(--ink-soft); margin: 0 .35rem .35rem 0; }

/* =============================================================== reviews */

/* Stars are gold on both cards and the product page; the numeric value beside them is what a
   screen reader gets, so the colour is carrying no information on its own. */
.stars { display: inline-flex; align-items: center; gap: .4rem; font-size: .85rem; white-space: nowrap; }
.stars__glyphs { color: #e0a800; letter-spacing: .05em; }
.stars__value { font-weight: 700; color: var(--ink); }
.stars__count { color: var(--ink-soft); }
.stars--empty .stars__none { color: var(--ink-soft); font-size: .82rem; font-style: italic; }

.reviews { margin-top: 3rem; }
.reviews__summary { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.review { border-top: 1px solid var(--line); padding: 1.1rem 0; }
.review__head { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; margin-bottom: .4rem; }
.review__author { font-weight: 600; }
.review__date { color: var(--ink-soft); font-size: .82rem; }
.review__body { margin: 0; color: var(--ink); }
.review__body--empty { color: var(--ink-soft); font-style: italic; }

/* The form only ever renders for somebody who has completed the assessment, so it is styled as a
   panel rather than a call to action - it is a task they have earned, not one being sold to them. */
.review-form { border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 1.4rem; background: var(--surface-alt); margin-top: 1.5rem; }
.review-form textarea { width: 100%; border: 1px solid var(--line-strong); border-radius: var(--radius); padding: .6rem .75rem; font: inherit; resize: vertical; min-height: 90px; }

/* Radio stars: the input stays focusable and is only visually replaced, so keyboard and screen
   reader users get a normal radio group rather than a widget they cannot operate. */
.star-input { display: inline-flex; flex-direction: row-reverse; gap: .15rem; }
.star-input input { position: absolute; opacity: 0; width: 0; height: 0; }
.star-input label { cursor: pointer; font-size: 1.5rem; color: var(--line-strong); line-height: 1; transition: color var(--speed) var(--ease); }
.star-input label:hover,
.star-input label:hover ~ label,
.star-input input:checked ~ label { color: #e0a800; }
.star-input input:focus-visible + label { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 3px; }

/* =============================================================== pricing */

.plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(258px, 1fr)); gap: 1.5rem; align-items: stretch; }
.plan {
  display: flex; flex-direction: column; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 1.75rem;
  position: relative; transition: box-shadow var(--speed) var(--ease), border-color var(--speed) var(--ease);
}
.plan:hover { box-shadow: var(--shadow-md); }
.plan--featured { border-color: var(--brand); box-shadow: var(--shadow-md); }
.plan__flag {
  position: absolute; top: -.7rem; left: 1.5rem;
  background: var(--accent); color: var(--ink); font-size: .7rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em; padding: .18rem .6rem; border-radius: 20px;
}
.plan__name { font-size: .8rem; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-soft); font-weight: 700; margin-bottom: .5rem; }
.plan__price { font-size: 2.4rem; font-weight: 700; letter-spacing: -.03em; line-height: 1; color: var(--ink); }
.plan__price small { font-size: .92rem; font-weight: 500; color: var(--ink-soft); letter-spacing: 0; }
/* The commission is the number that decides whether a plan is worth buying, so it sits with the
   price rather than in a footnote. */
.plan__rate {
  margin: .75rem 0 0; padding: .5rem .7rem; border-radius: 8px;
  background: var(--brand-tint); border: 1px solid var(--brand-line);
  font-size: .82rem; color: var(--ink-soft);
}
.plan__rate-value { font-weight: 700; color: var(--brand); font-size: .95rem; }
/* Who the tier is for, between the price and the list of what it contains. */
.plan__audience { margin: .8rem 0 0; font-size: .86rem; color: var(--ink-soft); }
.plan__list { list-style: none; padding: 0; margin: 1rem 0 1.6rem; font-size: .9rem; }
.plan__list li { position: relative; padding-left: 1.6rem; margin-bottom: .5rem; color: var(--ink-soft); }
.plan__list li i { position: absolute; left: 0; top: .28rem; font-size: .8rem; width: 1rem; }
.plan__list li i.fa-check { color: var(--brand); }
.plan__list li i.fa-times { color: var(--ink-faint); }
.plan__list li.is-excluded { color: var(--ink-faint); }
.plan__action { margin-top: auto; }

/* The commission line is the single most important number for a publisher deciding to list. */
.rate-band {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 1.75rem;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 1.75rem 2rem;
}
.rate { display: flex; flex-direction: column; gap: .2rem; }
.rate__value { font-size: 1.75rem; font-weight: 700; letter-spacing: -.02em; color: var(--brand); line-height: 1.1; }
.rate__label { font-size: .93rem; font-weight: 600; }
.rate__note { font-size: .85rem; color: var(--ink-soft); }

/* ============================================================= CTA band */

.cta-band {
  position: relative; overflow: hidden; isolation: isolate;
  background: linear-gradient(135deg, var(--brand-deep) 0%, var(--brand) 55%, #b0231d 100%);
  color: #fff; border-radius: var(--radius-lg); padding: 3.25rem 2.5rem; text-align: center;
}
.cta-band::after {
  content: ""; position: absolute; z-index: -1; left: -6rem; top: 50%; width: 34rem; height: 34rem; transform: translateY(-50%);
  background: conic-gradient(from 200deg at 0% 50%,
      rgba(255,195,37,.34) 0deg, rgba(255,195,37,0) 10deg,
      rgba(255,195,37,.28) 18deg, rgba(255,195,37,0) 28deg,
      rgba(255,195,37,.22) 36deg, rgba(255,195,37,0) 46deg, transparent 360deg);
  pointer-events: none;
}
.cta-band h2 { color: #fff; font-size: clamp(1.6rem, 1.2rem + 1.3vw, 2.1rem); }
.cta-band p { color: rgba(255,255,255,.86); max-width: 36rem; margin: 0 auto 1.75rem; }
.cta-band .btn-primary { background: #fff; border-color: #fff; color: var(--brand); }
.cta-band .btn-primary:hover { background: var(--accent); border-color: var(--accent); color: var(--ink); }
.cta-band .btn-outline-dark { background: transparent; border-color: rgba(255,255,255,.5); color: #fff; }
.cta-band .btn-outline-dark:hover { border-color: #fff; background: rgba(255,255,255,.1); color: #fff; }
.cta-band__actions { display: flex; gap: .8rem; justify-content: center; flex-wrap: wrap; }
.cta-band__note { margin: 1.5rem 0 0; font-size: .84rem; color: rgba(255,255,255,.72); }

/* ================================================================ footer */

.site-footer { border-top: 1px solid var(--line); padding: 3.5rem 0 2rem; background: var(--surface-alt); margin-top: 0; }
.footer-grid { display: grid; grid-template-columns: 1.9fr 1fr 1fr 1fr; gap: 2rem; }
.footer-blurb { color: var(--ink-soft); font-size: .9rem; max-width: 23rem; margin-top: .85rem; }
.footer-heading { font-size: .76rem; text-transform: uppercase; letter-spacing: .09em; color: var(--ink); font-weight: 700; margin-bottom: .1rem; }
.site-footer ul { list-style: none; padding: 0; margin: .7rem 0 0; }
.site-footer li { margin-bottom: .45rem; }
.site-footer a:not(.brand) { color: var(--ink-soft); font-size: .9rem; }
.site-footer a:not(.brand):hover { color: var(--brand); }
.footer-payments { display: flex; align-items: center; gap: .6rem; margin-top: 1.4rem; font-size: .8rem; color: var(--ink-faint); }
.footer-payments img { height: 17px; width: auto; opacity: .65; }
.footer-legal {
  margin: 2.75rem 0 0; padding-top: 1.5rem; border-top: 1px solid var(--line);
  font-size: .82rem; color: var(--ink-soft);
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
}

/* ============================================================ pagination */

.pagination { display: flex; gap: .35rem; list-style: none; padding: 0; margin: 2.5rem 0 0; flex-wrap: wrap; }
.pagination .page-link { display: inline-block; padding: .5rem .85rem; border: 1px solid var(--line); border-radius: 8px; color: var(--ink); font-size: .9rem; background: var(--surface); }
.pagination .page-link:hover { border-color: var(--line-strong); text-decoration: none; }
.pagination .active .page-link { background: var(--brand); border-color: var(--brand); color: #fff; }
.pagination .disabled .page-link { color: var(--ink-faint); background: var(--surface-alt); }

/* ======================================================== form controls */

.form-control, .field {
  width: 100%; border: 1px solid var(--line-strong); border-radius: 8px;
  padding: .65rem .85rem; font-size: .95rem; font-family: inherit; color: var(--ink);
  background: var(--surface); transition: border-color var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}
.form-control::placeholder { color: var(--ink-faint); }
.form-control:hover { border-color: var(--ink-faint); }
.form-control:focus { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(150,17,13,.13); outline: none; }
.form-control:disabled { background: var(--surface-alt); color: var(--ink-faint); cursor: not-allowed; }

.search-row { display: flex; gap: .5rem; max-width: 540px; }

/* ==================================================== authentication UI */

/*
  The sign-in and registration dialogs are AdminLTE markup shared with the back office. Rather than
  load AdminLTE's stylesheet on a public page for two dialogs, these are the rules they need on top
  of Bootstrap - now matching the rest of the public design system rather than sitting inside it as
  a foreign object.
*/
.login-logo { text-align: center; margin-bottom: .85rem; }
/* Was #fff on a white page, which put an invisible wordmark over the sticky header on small
   screens. It is the dialog's own title, so it is ink on the backdrop's dim. */
.login-logo a { color: #fff; font-size: 1.25rem; font-weight: 600; text-shadow: 0 1px 12px rgba(0,0,0,.55); }
.login-logo a:hover { text-decoration: none; }
.login-logo b { color: var(--accent); }

.modal-content.login-box, .log-in-card { border-radius: var(--radius-lg); border: none; }
.modal-content.login-box { overflow: auto; max-height: 86vh; box-shadow: var(--shadow-lg); }
.login-card-body { padding: 1.6rem; }
.login-box-msg { text-align: center; margin-bottom: 1.15rem; font-weight: 600; font-size: 1.05rem; color: var(--ink); }

/* Bootstrap's .close is a 1rem glyph in the corner with no hit area to speak of; on a phone that is
   the only way out of the dialog, so it gets a real 40px target. */
.modal-content.login-box { position: relative; }
.auth-close {
  position: absolute; top: .6rem; right: .6rem; z-index: 3;
  width: 40px; height: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-alt); border: 1px solid var(--line); color: var(--ink-soft);
  font-size: 1.35rem; line-height: 1; cursor: pointer; padding: 0;
  opacity: 1; text-shadow: none; font-weight: 400;
}
.auth-close:hover, .auth-close:focus { background: var(--brand-tint); border-color: var(--brand-line); color: var(--brand); opacity: 1; }

.login-card-body .input-group-text { background: var(--surface-alt); border-color: var(--line-strong); color: var(--ink-faint); }
.login-card-body .form-control { border-color: var(--line-strong); }
.login-card-body .btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.login-card-body .btn-primary:hover { background: var(--brand-deep); border-color: var(--brand-deep); }
/* Bootstrap's checkbox is a 13px target; the terms box is a required step on a phone. */
.login-card-body .icheck-primary input[type="checkbox"],
.login-card-body input[type="checkbox"] { width: 18px; height: 18px; }
.login-card-body label { font-size: .92rem; }

/* ========================================================== reveal motion */

/*
  Sections fade up once as they enter. `.reveal` only does anything after the script adds
  `js-reveal` to <html>, so with JavaScript unavailable everything is simply visible - motion never
  decides whether content renders.
*/
.js-reveal .reveal { opacity: 0; transform: translateY(14px); }
.js-reveal .reveal.is-visible {
  opacity: 1; transform: none;
  transition: opacity 520ms var(--ease), transform 520ms var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .js-reveal .reveal { opacity: 1; transform: none; }
  .listing:hover { transform: none; }
  .listing:hover .listing__media { transform: none; }
  .template-card:hover { transform: none; }
  .btn:active { transform: none; }
}

/* ============================================================ responsive */

@media (max-width: 980px) {
  .flow { grid-template-columns: 1fr; gap: 2.25rem; }
  .listing-hero { grid-template-columns: 1fr; }
  .buy-box { position: static; }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 2rem 1.5rem; }
}

@media (max-width: 900px) {
  .template-grid, .capabilities { grid-template-columns: repeat(2, 1fr); }
  .hero { padding: 2.5rem 0 3rem; }
  .hero-grid { grid-template-columns: 1fr; gap: 2.25rem; }
  .audience-grid { grid-template-columns: 1fr; }
  .section { padding: 3.25rem 0; }
  .section--tight { padding: 2.5rem 0; }
  .section-head { margin-bottom: 2rem; }


  .hero-actions .btn { flex: 1 1 100%; }
  .hero-trust { gap: .75rem 1.5rem; margin-top: 1.75rem; padding-top: 1.25rem; }
  .cta-band { padding: 2.5rem 1.5rem; }
  .cta-band__actions .btn { flex: 1 1 100%; }
}

/*
  Below this width the page stops stacking and starts swiping.

  Stacking the three "how it works" panels put three screen-heights of product mockup between the
  hero and the marketplace - the section alone measured 1451px on a 390px-wide phone, and a visitor
  had to scroll past all of it to reach anything they could act on. As one snapping row it is a
  single screen, and comparing the three steps is a thumb movement rather than a memory exercise.
*/
@media (max-width: 760px) {
  .flow {
    grid-auto-flow: column; grid-auto-columns: 84%; grid-template-columns: none;
    overflow-x: auto; scroll-snap-type: x mandatory;
    margin-inline: -20px; padding: .25rem 20px 1rem; gap: 1rem;
    scrollbar-width: none;
  }
  .flow::-webkit-scrollbar { display: none; }
  .flow__step { scroll-snap-align: start; gap: .75rem; }
  .flow__step > p { font-size: .88rem; }
}

@media (max-width: 640px) {
  /*
    Mobile is not the desktop layout stacked. Two columns for the small, scannable grids keeps the
    page from becoming a mile of single cards - the capability and template lists alone ran to most
    of a screen each when every item was full width.
  */
  .template-grid, .capabilities { grid-template-columns: 1fr 1fr; gap: 1rem; }
  .capabilities { gap: 1.4rem 1rem; }
  .capability i { width: 30px; height: 30px; margin-bottom: .5rem; }
  .capability h3 { font-size: .92rem; }
  .capability p { font-size: .84rem; }
  .template-card { padding: .9rem; }
  .template-card__dims { display: none; }
  /* Six summaries at full length was most of a screen of grey text. Two lines each is enough to
     tell a reader what the subject is, which is all this grid is for. */
  .template-card p { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

  /* Tighter panels: the same words, less of the phone. */
  .audience { padding: 1.35rem 1.25rem; }
  .audience h3 { font-size: 1.1rem; }
  .audience > p { font-size: .92rem; margin-bottom: .5rem; }
  .audience ul { margin-top: .9rem; }
  .audience li { font-size: .89rem; margin-bottom: .5rem; padding-left: 1.4rem; }

  /* Three trust items each on their own line pushed the product preview below the fold. */
  .hero-trust { gap: .55rem 1.1rem; }
  .hero-trust__item { font-size: .8rem; }
  .hero .lede { font-size: 1.04rem; }

  .rate-band { padding: 1.25rem; gap: 1.1rem; }
  .rate__value { font-size: 1.55rem; }
  .rate__note { font-size: .82rem; }

  /* A catalogue reads better swiped than scrolled when the cards are full-bleed anyway. */
  .listing-grid {
    grid-auto-flow: column; grid-auto-columns: 82%; grid-template-columns: none;
    overflow-x: auto; scroll-snap-type: x mandatory;
    margin-inline: -20px; padding: .25rem 20px 1rem; gap: 1rem;
    scrollbar-width: none;
  }
  .listing-grid::-webkit-scrollbar { display: none; }
  .listing { scroll-snap-align: start; }
  .listing:hover { transform: none; }

  .rate-band { padding: 1.4rem; gap: 1.25rem; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .section-head-row { gap: 1.25rem; }
  .section-head-row > .btn { width: 100%; }

  /* The dialog's wordmark sat in white over the page behind it, colliding with the site header at
     the top of a small screen. The dialog states what it is in its own heading, so on a phone the
     duplicate goes and the vertical space goes to the form. */
  .login-logo { display: none; }
  .modal-dialog { margin: .5rem; }
  .modal-content.login-box { max-height: 92vh; }
  .login-card-body { padding: 1.35rem 1.1rem; }
  .login-box-msg { padding-right: 2.5rem; text-align: left; }
}

/*
  Small phones.

  The header row - wordmark, a persistent "Get started", and the menu button - measured 391px of
  content and pushed the whole document to 411px wide on a 360px screen, which is a sideways scroll
  on every page. Rather than dropping the call to action (the reason it is in the bar at all) or the
  brand, everything in the row gives back a few pixels.
*/
@media (max-width: 420px) {
  .container { padding: 0 16px; }
  .listing-grid, .flow { margin-inline: -16px; padding-inline: 16px; }
  .cta-band { padding: 2.25rem 1.25rem; }
}

/* Narrower still (iPhone SE and similar). The wordmark goes and the mark stays: it is the half of
   the logo that is recognisable at 22px anyway, and the link keeps its name from aria-label. */
@media (max-width: 360px) {
  .hero h1 { font-size: 1.95rem; }
}

@media print {
  .site-header, .site-footer, .skip-link, .nav-toggle { display: none; }
  .ray-field::before, .ray-field::after, .cta-band::after { display: none; }
  /* A section that has not been scrolled past is still hidden when the print job runs, which would
     put blank pages in the output. Print always shows everything. */
  .js-reveal .reveal { opacity: 1 !important; transform: none !important; }
}
