/* ===========================================================================
   COMPONENTS — TestPrep's own patterns, the `.tp-*` classes. DDR-0010.

   Taken from the exam-portal prototype in docs/source-material: the navy band,
   the white card, the gold action, the status pill, the icon tile. Every value
   that carries meaning is a `var(--tp-*)` from design-tokens.css. **This file
   may not state a colour or a shadow of its own**, and PaletteContrastTests
   fails on a hex here exactly as it does anywhere outside the token file. A few
   small paddings are literal, quoted from the prototype's Tailwind classes; the
   moment a designer wants to move one, it becomes a token rather than an edit
   here.

   What is NOT here: restyling Bootstrap's own classes (`.card`, `.btn-*`,
   `.form-control`, `.table`). That is bootstrap-bridge.css, because it is
   Bootstrap being handed our values. One component lives in one file.

   The style guide's Components tab shows every class below, and it is still
   hand-written markup rather than rendered partials — ADR-0028's component
   inventory is the follow-up that closes that gap.
   =========================================================================== */

/* --- Layout --------------------------------------------------------------- */

.tp-container {
  max-width: var(--tp-content-width);
  margin-inline: auto;
  padding-inline: var(--tp-space-3);
}

.tp-container-narrow {
  max-width: var(--tp-content-width-narrow);
}

.tp-page {
  padding-block: var(--tp-space-section) var(--tp-space-5);
}

/* Vertical rhythm between a page's sections — the prototype's space-y-6. Opt-in
   rather than applied to every page, so a page that has not been laid out this
   way keeps its own margins. */
.tp-stack > * {
  margin-block: 0;
}

.tp-stack > * + * {
  margin-top: var(--tp-space-section);
}

/* Cards in a grid: one column, two from a small tablet, three on a desktop. */
.tp-grid {
  display: grid;
  gap: var(--tp-space-grid);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 576px) {
  .tp-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 992px) {
  .tp-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* Two cards side by side from a tablet up, tops aligned — the prototype's
   "grid md:grid-cols-2 gap-5 items-start". The sidebar variant is one part to
   two, for a stat beside a list, and waits for a desktop: the list beside it
   is usually a table, and a table in two-thirds of a tablet is a scroll bar. */
.tp-columns {
  display: grid;
  gap: var(--tp-space-card);
  align-items: start;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 768px) {
  .tp-columns {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tp-columns-sidebar {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (min-width: 992px) {
  .tp-columns-sidebar {
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  }
}

/* --- Icons ----------------------------------------------------------------
   Inline SVG, always aria-hidden: an icon beside a word adds nothing a screen
   reader needs, and an icon *instead of* a word is not allowed (ADR-0022). */

.tp-icon {
  width: var(--tp-size-icon);
  height: var(--tp-size-icon);
  flex-shrink: 0;
  vertical-align: -0.125em;
}

/* One picture for every test. The prototype gives each exam its own emoji,
   which needs a per-test setting nothing in Surpass supplies — so every test
   gets the practice test's pencil. */
.tp-test-icon {
  font-size: var(--tp-text-2xl);
  line-height: 1;
  flex-shrink: 0;
}

.tp-test-icon-lg {
  font-size: var(--tp-text-4xl);
}

/* --- The header: navigation on the navy band ------------------------------ */

.tp-header {
  background-color: var(--tp-band);
  color: var(--tp-on-band);
}

.tp-nav {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--tp-space-grid);
  padding-block: var(--tp-space-2);
}

.tp-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--tp-space-2);
  color: var(--tp-on-band);
  font-weight: var(--tp-weight-extrabold);
  text-decoration: none;
}

.tp-brand:hover {
  color: var(--tp-on-band);
}

.tp-brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--tp-size-mark) * 0.8);
  height: calc(var(--tp-size-mark) * 0.8);
  border-radius: var(--tp-radius-sm);
  background-color: var(--tp-surface);
  color: var(--tp-heading);
}

.tp-nav-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tp-nav-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.75rem;
  border-radius: var(--tp-radius-sm);
  font-size: var(--tp-text-xs);
  font-weight: var(--tp-weight-bold);
  color: var(--tp-on-band-muted);
  text-decoration: none;
}

.tp-nav-link:hover {
  color: var(--tp-on-band);
  background-color: var(--tp-band-raised);
}

/* Where you are. Gold, as the prototype's selected role is — and gold on navy
   is 9.89:1, so the difference between current and not is not colour alone. */
.tp-nav-link[aria-current="page"] {
  color: var(--tp-on-action);
  background-color: var(--tp-action);
}

.tp-nav-spacer {
  flex: 1;
}

.tp-identity {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--tp-space-2);
  font-size: var(--tp-text-xs);
  color: var(--tp-on-band-muted);
}

.tp-identity strong {
  color: var(--tp-on-band);
}

.tp-nav-button {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.75rem;
  border: var(--tp-border-width) solid var(--tp-on-band-muted);
  border-radius: var(--tp-radius-sm);
  background: none;
  color: var(--tp-on-band);
  font-size: var(--tp-text-xs);
  font-weight: var(--tp-weight-bold);
  text-decoration: none;
}

.tp-nav-button:hover {
  color: var(--tp-on-band);
  background-color: var(--tp-band-raised);
}

.tp-nav-button-action {
  border-color: var(--tp-action);
  background-color: var(--tp-action);
  color: var(--tp-on-action);
}

.tp-nav-button-action:hover {
  border-color: var(--tp-action-hover);
  background-color: var(--tp-action-hover);
  color: var(--tp-on-action);
}

/* The dark focus ring is invisible on navy, so anything focusable on the band
   gets the gold one. Specific enough to beat site.css's `a:focus-visible` and
   `.btn:focus-visible` without !important. */
.tp-header :is(a, button):focus-visible,
.tp-band :is(a, button):focus-visible {
  outline-color: var(--tp-focus-on-band);
}

/* --- The band: the page's own heading, on navy --------------------------- */

.tp-band {
  background-color: var(--tp-band);
  color: var(--tp-on-band);
  border-top: 1px solid var(--tp-band-raised);
}

.tp-band-inner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--tp-space-grid);
  padding-block: var(--tp-space-card);
}

.tp-band-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--tp-size-mark);
  min-width: var(--tp-size-mark);
  padding: var(--tp-space-1) var(--tp-space-2);
  border-radius: var(--tp-radius-sm);
  background-color: var(--tp-surface);
  color: var(--tp-heading);
}

.tp-band-mark .tp-icon {
  width: var(--tp-size-icon-lg);
  height: var(--tp-size-icon-lg);
}

.tp-band-text {
  flex: 1;
  min-width: 11.25rem;
}

.tp-band-eyebrow {
  margin: 0;
  font-size: var(--tp-text-2xs);
  font-weight: var(--tp-weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--tp-tracking-widest);
  color: var(--tp-on-band-muted);
}

.tp-band-title {
  margin: 0;
  font-size: var(--tp-text-xl);
  font-weight: var(--tp-weight-black);
  line-height: var(--tp-leading-tight);
  color: var(--tp-on-band);
}

.tp-band-subtitle {
  margin: 0;
  font-size: var(--tp-text-xs);
  color: var(--tp-on-band-muted);
}

/* Inline code and links on navy: magenta and navy text would vanish. */
.tp-band code,
.tp-band a {
  color: var(--tp-on-band);
}

.tp-band-aside {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--tp-space-2);
}

/* --- Headings inside the page -------------------------------------------- */

.tp-section-title {
  display: flex;
  align-items: center;
  gap: var(--tp-space-2);
  margin: 0 0 var(--tp-space-grid);
  font-size: var(--tp-text-base);
  font-weight: var(--tp-weight-extrabold);
  line-height: var(--tp-leading-tight);
  color: var(--tp-heading);
}

.tp-section-lede {
  margin: calc(var(--tp-space-1) * -1) 0 var(--tp-space-grid);
  font-size: var(--tp-text-sm);
  color: var(--tp-ink-muted);
}

.tp-card-title {
  margin: 0 0 var(--tp-space-1);
  font-size: var(--tp-text-base);
  font-weight: var(--tp-weight-extrabold);
  line-height: var(--tp-leading-tight);
  color: var(--tp-heading);
}

.tp-card-lede {
  margin: 0 0 var(--tp-space-3);
  font-size: var(--tp-text-xs);
  color: var(--tp-ink-muted);
}

/* A small uppercase label: "Credit balance", "Add a centre". */
.tp-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0 0 var(--tp-space-2);
  font-size: var(--tp-text-xs);
  font-weight: var(--tp-weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--tp-tracking-wide);
  line-height: var(--tp-leading-base);
  color: var(--tp-ink-muted);
}

/* --- Cards --------------------------------------------------------------- */

/* The smaller card the prototype uses for one test: p-4 rather than p-5. */
.tp-card-compact {
  --bs-card-spacer-x: var(--tp-space-card-compact);
  --bs-card-spacer-y: var(--tp-space-card-compact);
}

/* A panel inside a card: bordered rather than raised. */
.tp-panel {
  border: var(--tp-border-width) solid var(--tp-rule);
  border-radius: var(--tp-radius-md);
  padding: var(--tp-space-card-compact);
}

/* A card with its rows running edge to edge, divided by a rule. */
.tp-rows > .tp-row + .tp-row {
  border-top: 1px solid var(--tp-rule);
}

.tp-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--tp-space-grid);
  padding-block: var(--tp-space-grid);
}

.tp-rows-padded > .tp-row {
  padding: var(--tp-space-card-compact);
}

.tp-row-main {
  flex: 1;
  min-width: 10.5rem;
}

.tp-title {
  font-size: var(--tp-text-sm);
  font-weight: var(--tp-weight-bold);
  color: var(--tp-ink);
}

.tp-meta {
  font-size: var(--tp-text-xs);
  color: var(--tp-ink-muted);
}

.tp-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--tp-space-2);
}

/* --- Status pills -------------------------------------------------------- */

.tp-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--tp-space-1);
  padding: 0.125rem 0.625rem;
  border-radius: var(--tp-radius-pill);
  font-size: var(--tp-text-xs);
  font-weight: var(--tp-weight-bold);
  line-height: var(--tp-leading-base);
  white-space: nowrap;
}

.tp-pill .tp-icon {
  width: 0.75rem;
  height: 0.75rem;
}

.tp-pill-success { background-color: var(--tp-success-surface); color: var(--tp-success); }
.tp-pill-warning { background-color: var(--tp-warning-surface); color: var(--tp-warning-ink); }
.tp-pill-danger { background-color: var(--tp-danger-surface); color: var(--tp-danger); }
.tp-pill-info { background-color: var(--tp-info-surface); color: var(--tp-info-ink); }
.tp-pill-neutral { background-color: var(--tp-neutral-surface); color: var(--tp-ink-muted); }
.tp-pill-highlight { background-color: var(--tp-highlight-surface); color: var(--tp-heading); }
.tp-pill-action { background-color: var(--tp-action); color: var(--tp-on-action); }
.tp-pill-on-band { background-color: var(--tp-band-raised); color: var(--tp-on-band); }

/* --- Icon tiles and avatars --------------------------------------------- */

.tp-icon-tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tp-size-tile);
  height: var(--tp-size-tile);
  border-radius: var(--tp-radius-md);
  color: var(--tp-on-accent);
}

.tp-icon-tile .tp-icon {
  width: var(--tp-size-icon-lg);
  height: var(--tp-size-icon-lg);
}

.tp-icon-tile-organisation { background-color: var(--tp-tile-organisation); }
.tp-icon-tile-centre { background-color: var(--tp-tile-centre); }
.tp-icon-tile-candidate { background-color: var(--tp-tile-candidate); }

.tp-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--tp-size-avatar);
  height: var(--tp-size-avatar);
  border-radius: var(--tp-radius-pill);
  background-color: var(--tp-avatar-surface);
  color: var(--tp-heading);
  font-size: var(--tp-text-sm);
  font-weight: var(--tp-weight-extrabold);
}

/* --- A number that matters: "42 credits available" ---------------------- */

.tp-stat {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: var(--tp-space-2);
  margin-bottom: var(--tp-space-1);
}

.tp-stat-value {
  font-size: var(--tp-text-4xl);
  font-weight: var(--tp-weight-black);
  line-height: 1;
  color: var(--tp-heading);
}

.tp-stat-label {
  padding-bottom: 0.25rem;
  font-size: var(--tp-text-sm);
  font-weight: var(--tp-weight-bold);
  color: var(--tp-ink-muted);
}

.tp-callout {
  padding: var(--tp-space-grid);
  border-radius: var(--tp-radius-md);
  background-color: var(--tp-highlight-surface);
  color: var(--tp-heading);
  font-size: var(--tp-text-xs);
  line-height: var(--tp-leading-relaxed);
}

/* --- Empty states -------------------------------------------------------- */

.tp-empty {
  padding: var(--tp-space-5) var(--tp-space-3);
  border: var(--tp-border-width) dashed var(--tp-border);
  border-radius: var(--tp-radius-lg);
  text-align: center;
  font-size: var(--tp-text-sm);
  color: var(--tp-ink-muted);
}

/* --- The landing page ---------------------------------------------------- */

.tp-landing {
  padding-block: var(--tp-space-5);
}

.tp-hero {
  margin-bottom: var(--tp-space-hero);
  text-align: center;
}

.tp-hero-mark {
  display: inline-flex;
  align-items: center;
  gap: var(--tp-space-grid);
  margin-bottom: var(--tp-space-4);
  padding: var(--tp-space-3) var(--tp-space-4);
  border-radius: var(--tp-radius-lg);
  background-color: var(--tp-surface);
  box-shadow: var(--tp-elev-1);
}

.tp-wordmark {
  margin: 0;
  font-size: var(--tp-text-2xl);
  font-weight: var(--tp-weight-black);
  line-height: var(--tp-leading-tight);
  color: var(--tp-heading);
}

.tp-hero-lead {
  max-width: 48rem;
  margin: 0 auto;
  font-size: var(--tp-text-lg);
  font-weight: var(--tp-weight-bold);
  line-height: var(--tp-leading-snug);
  color: var(--tp-heading);
}

@media (min-width: 576px) {
  .tp-hero-lead {
    font-size: var(--tp-text-xl);
  }
}

/* One card per way in. The whole card is the target — the link inside it is a
   Bootstrap .stretched-link — and it lifts on hover or when its link has focus. */
.tp-choice {
  position: relative;
  height: 100%;
  padding: var(--tp-space-card);
  border: var(--tp-border-width) solid transparent;
  border-radius: var(--tp-radius-lg);
  background-color: var(--tp-surface);
  box-shadow: var(--tp-elev-1);
  transition: box-shadow var(--tp-transition), transform var(--tp-transition), border-color var(--tp-transition);
}

.tp-choice:hover,
.tp-choice:focus-within {
  border-color: var(--tp-action);
  box-shadow: var(--tp-elev-3);
  transform: translateY(var(--tp-lift));
}

@media (prefers-reduced-motion: reduce) {
  .tp-choice {
    transition: none;
  }

  .tp-choice:hover,
  .tp-choice:focus-within {
    transform: none;
  }
}

/* A way in that does not exist yet (the site administrator, ADR-0037). Not a control, so it must not
   look like one: no lift, no elevation, a dashed edge. Its text keeps the colours the other cards use,
   on the same surface, so nothing here changes a measured contrast. */
.tp-choice-unavailable,
.tp-choice-unavailable:hover,
.tp-choice-unavailable:focus-within {
  border: var(--tp-border-width) dashed var(--tp-border);
  box-shadow: none;
  transform: none;
}

.tp-choice .tp-icon-tile {
  margin-bottom: var(--tp-space-3);
}

.tp-choice-title {
  margin: 0;
  font-size: var(--tp-text-sm);
  font-weight: var(--tp-weight-extrabold);
  color: var(--tp-ink);
}

.tp-choice-audience {
  margin: 0 0 var(--tp-space-2);
  font-size: var(--tp-text-xs);
  font-weight: var(--tp-weight-bold);
  color: var(--tp-link);
}

.tp-choice-text {
  margin: 0;
  font-size: var(--tp-text-xs);
  line-height: var(--tp-leading-snug);
  color: var(--tp-ink-muted);
}

.tp-choice-link {
  display: inline-flex;
  align-items: center;
  gap: var(--tp-space-1);
  margin-top: var(--tp-space-grid);
  font-size: var(--tp-text-xs);
  font-weight: var(--tp-weight-bold);
  color: var(--tp-link);
  text-decoration: none;
}

/* A form on its own — sign-in, set a password. */
.tp-form-card {
  max-width: var(--tp-form-width);
}

/* The frame around an AO's custom report (ADR-0038). The report inside is the AO's own HTML and carries
   its own styles; only the frame is ours. Tall enough to read without the page scrolling twice. */
.tp-report-frame {
  display: block;
  width: 100%;
  min-height: 75vh;
  border: var(--tp-border-width) solid var(--tp-rule);
  border-radius: var(--tp-radius-sm);
  background: var(--tp-surface);
}
