/* =========================================================================
   Site surfaces
   The homepage sections and the three public directories: services, tools and
   scholarships. Depends on tokens.css; adds no colours of its own.

   Grid rule throughout: `repeat(auto-fill, minmax(min(100%, Xrem), 1fr))`.
   The `min(100%, …)` is what stops a card overflowing its track below the
   stated minimum, which is the usual cause of a page that scrolls sideways on
   a 320px phone.
   ========================================================================= */

/* -------------------------------------------------------------------------
   Homepage hero
   ------------------------------------------------------------------------- */
.home-hero {
  position: relative;
  padding-block: var(--space-16) var(--space-12);
  background: var(--gradient-mesh);
  overflow: hidden;
}

.home-hero-inner {
  display: grid;
  gap: var(--space-10);
  align-items: center;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 940px) {
  .home-hero-inner { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
}

.home-hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.3rem var(--space-3);
  margin-bottom: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-muted);
}

.home-hero-title {
  font-size: var(--text-4xl);
  font-weight: var(--weight-black);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--text);
  text-wrap: balance;
  margin-bottom: var(--space-4);
}

.home-hero-desc {
  font-size: var(--article-lead);
  line-height: var(--leading-snug);
  color: var(--text-muted);
  max-width: 46ch;
  text-wrap: pretty;
}

.home-hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-8);
}
@media (max-width: 460px) {
  .home-hero-actions { flex-direction: column; align-items: stretch; }
  .home-hero-actions .btn { width: 100%; }
}

/* Search field that sits under the hero copy. */
.home-search {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 34rem;
  margin-top: var(--space-6);
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  box-shadow: var(--shadow-md);
}
.home-search input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--text);
  outline: none;
}
.home-search input::placeholder { color: var(--text-subtle); }
.home-search:focus-within { box-shadow: var(--shadow-md), var(--focus-ring); }

/* -------------------------------------------------------------------------
   Services
   ------------------------------------------------------------------------- */
.service-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
}

.service-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
  transition: transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out);
}
.service-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--gradient-brand);
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-out);
}
.service-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.service-card:hover::before { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .service-card, .service-card:hover { transition: none; transform: none; }
}

.service-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: var(--radius-md);
  background: var(--brand-50);
  color: var(--brand-600);
  font-size: var(--text-xl);
}

.service-name {
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-snug);
  color: var(--text);
}
.service-tagline { font-size: var(--text-base); line-height: var(--leading-normal); color: var(--text-muted); }
.service-link {
  margin-top: auto;
  padding-top: var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-brand);
}
.service-link::after {
  content: " \2192";
  transition: transform var(--duration-fast) var(--ease-out);
  display: inline-block;
}
.service-card:hover .service-link::after { transform: translateX(3px); }

/* -------------------------------------------------------------------------
   Tools
   The tier badge and the locked state both read from the same data attribute
   the plan gate uses, so the badge on the card can never disagree with what
   the middleware actually enforces.
   ------------------------------------------------------------------------- */
.tool-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
}

.tool-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out);
}
.tool-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: var(--brand-300);
}
@media (prefers-reduced-motion: reduce) {
  .tool-card, .tool-card:hover { transition: none; transform: none; }
}

.tool-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.tool-icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  color: var(--text-brand);
  font-size: var(--text-lg);
  flex: none;
}

.tool-name {
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  color: var(--text);
}
.tool-summary {
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-muted);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  line-clamp: 3;
  overflow: hidden;
}

.tool-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}

.tier-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0.2rem var(--space-2);
  border-radius: var(--radius-xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
}
.tier-badge[data-tier="FREE"]    { color: var(--tier-free-fg);    background: var(--tier-free-bg); }
.tier-badge[data-tier="TRIAL"]   { color: var(--tier-trial-fg);   background: var(--tier-trial-bg); }
.tier-badge[data-tier="PREMIUM"] { color: var(--tier-premium-fg); background: var(--tier-premium-bg); }

/* A locked tool is dimmed but never hidden: it is a landing page we want
   indexed and an upgrade prompt we want seen. */
.tool-card[data-locked="1"] .tool-icon { color: var(--text-subtle); }
.tool-card[data-locked="1"] .tool-name { color: var(--text-muted); }
.tool-lock {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--text-subtle);
}

.tool-trial-note {
  font-size: var(--text-xs);
  color: var(--text-subtle);
}

/* Tool workspace - the two-pane run screen (inputs left, result right). */
.tool-shell {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
@media (min-width: 900px) {
  .tool-shell { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); }
  .tool-shell-inputs { position: sticky; top: calc(var(--header-height) + var(--space-5)); }
}
.tool-result {
  min-height: 18rem;
  padding: var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

/* Upgrade wall shown in place of the run button for a gated tool. */
.upgrade-wall {
  display: grid;
  gap: var(--space-3);
  place-items: center;
  padding: var(--space-8) var(--space-6);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface-alt);
  text-align: center;
}
.upgrade-wall-title { font-size: var(--text-lg); font-weight: var(--weight-bold); color: var(--text); }
.upgrade-wall-text { font-size: var(--text-base); color: var(--text-muted); max-width: 40ch; }

/* -------------------------------------------------------------------------
   Scholarships
   ------------------------------------------------------------------------- */
.scholarship-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
}

.scholarship-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: box-shadow var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out);
}
.scholarship-card:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); }

.scholarship-provider {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
}
.scholarship-title {
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  color: var(--text);
}
.scholarship-card:hover .scholarship-title { color: var(--text-brand); }

.scholarship-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: var(--text-xs);
}
.scholarship-fact {
  padding: 0.2rem var(--space-2);
  border-radius: var(--radius-xs);
  background: var(--bg-sunken);
  color: var(--text-muted);
}

.deadline-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0.2rem var(--space-2);
  border-radius: var(--radius-xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}
.deadline-pill[data-state="open"]   { color: var(--deadline-open-fg);   background: var(--deadline-open-bg); }
.deadline-pill[data-state="soon"]   { color: var(--deadline-soon-fg);   background: var(--deadline-soon-bg); }
.deadline-pill[data-state="closed"] { color: var(--deadline-closed-fg); background: var(--deadline-closed-bg); }

/* -------------------------------------------------------------------------
   Trending strip - the live-news ticker under the hero
   ------------------------------------------------------------------------- */
.trending {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-block: 1px solid var(--border);
  overflow: hidden;
}
.trending-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex: none;
  padding-right: var(--space-4);
  border-right: 1px solid var(--border);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--danger-500);
}
.trending-items {
  display: flex;
  gap: var(--space-6);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.trending-items::-webkit-scrollbar { display: none; }
.trending-item {
  flex: none;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text-muted);
  white-space: nowrap;
}
.trending-item:hover { color: var(--text-brand); }

/* -------------------------------------------------------------------------
   Shared section furniture for the homepage
   ------------------------------------------------------------------------- */
.home-section { padding-block: var(--space-16); }
.home-section + .home-section { padding-top: 0; }
.home-section-alt { background: var(--bg-sunken); }

.home-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-8);
}
.home-section-title {
  font-size: var(--text-3xl);
  font-weight: var(--weight-black);
  letter-spacing: var(--tracking-tight);
  color: var(--text);
  text-wrap: balance;
}
.home-section-desc {
  margin-top: var(--space-2);
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--text-muted);
  max-width: 56ch;
}

@media (max-width: 600px) {
  .home-section { padding-block: var(--space-12); }
  .home-section-head { margin-bottom: var(--space-6); }
}

/* A real programme whose current-cycle date is not yet confirmed. Neutral on
   purpose - it is an absence of information, not an urgency signal. */
.deadline-pill[data-state="tba"] { color: var(--text-muted); background: var(--bg-sunken); }

/* =========================================================================
   Carousel
   One component for Services, Tools, Scholarships and News.

   Built on native scroll-snap rather than a transform track, which means:
   touch and trackpad swiping work with no JS, the scrollbar position is the
   single source of truth (so arrows and dots can never drift out of sync with
   what is on screen), and if the script fails the section degrades to a
   horizontally scrollable row instead of a dead widget.

   Slides per view is set per instance with --slides-lg / --slides-md /
   --slides-sm, so one stylesheet serves a 4-card row and an 8-card row.
   ========================================================================= */
.carousel {
  --gap: var(--space-5);
  --slides: var(--slides-lg, 3);
  position: relative;
}

@media (max-width: 1023px) { .carousel { --slides: var(--slides-md, 2); } }
@media (max-width: 640px)  { .carousel { --slides: var(--slides-sm, 1.1); --gap: var(--space-4); } }

.carousel-viewport {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* NO `scroll-behavior: smooth` here, deliberately. In at least one engine a
     CSS-forced smooth scroll on this container never completes, which leaves
     scrollLeft pinned at 0 and the whole carousel dead. site.js tweens the
     scroll itself instead, which behaves identically everywhere. */
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* Room for the cards' hover lift and shadow, which would otherwise be
     clipped by the scroll container. */
  padding: var(--space-2) var(--space-1) var(--space-4);
  margin-inline: calc(var(--space-1) * -1);
}
.carousel-viewport::-webkit-scrollbar { display: none; }

.carousel-track {
  display: flex;
  gap: var(--gap);
  align-items: stretch;
}

.carousel-track > * {
  flex: 0 0 calc((100% - (var(--gap) * (var(--slides) - 1))) / var(--slides));
  scroll-snap-align: start;
  min-width: 0;
}

/* ---- arrows ----
   Sit outside the cards on wide screens and overlap the edge below that,
   because at narrow widths there is no gutter to sit in. */
.carousel-arrow {
  position: absolute;
  top: calc(50% - 22px);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-lg);
  transition: transform var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out),
              opacity var(--duration-base) var(--ease-out),
              visibility var(--duration-base);
}
.carousel-arrow:hover {
  background: var(--brand-600);
  border-color: var(--brand-600);
  color: var(--ink-0);
  transform: scale(1.08);
}
.carousel-arrow:active { transform: scale(0.96); }

.carousel-arrow.is-prev { left: calc(var(--space-6) * -1); }
.carousel-arrow.is-next { right: calc(var(--space-6) * -1); }

/* An arrow at the end of its travel is hidden rather than shown dead - a
   button that looks pressable and does nothing is worse than no button. */
.carousel-arrow[disabled] { opacity: 0; visibility: hidden; pointer-events: none; }

@media (max-width: 1279px) {
  .carousel-arrow.is-prev { left: calc(var(--space-2) * -1); }
  .carousel-arrow.is-next { right: calc(var(--space-2) * -1); }
}
@media (max-width: 640px) {
  .carousel-arrow { width: 38px; height: 38px; top: calc(50% - 19px); }
  .carousel-arrow.is-prev { left: 0; }
  .carousel-arrow.is-next { right: 0; }
}

/* Hidden entirely until the script confirms the track actually overflows. */
.carousel:not(.is-ready) .carousel-arrow,
.carousel:not(.is-ready) .carousel-dots { display: none; }

/* ---- dots ---- */
.carousel-dots {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.carousel-dot {
  width: 7px;
  height: 7px;
  border: 0;
  padding: 0;
  border-radius: var(--radius-pill);
  background: var(--border-strong);
  transition: width var(--duration-base) var(--ease-out),
              background var(--duration-base) var(--ease-out);
}
.carousel-dot:hover { background: var(--brand-400); }
.carousel-dot.is-active { width: 22px; background: var(--brand-600); }

/* ---- autoplay progress ----
   A hairline under an autoplaying carousel, so the movement is explained
   rather than just happening. Removed the moment the reader interacts. */
.carousel-progress {
  height: 2px;
  margin-top: var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--border);
  overflow: hidden;
}
.carousel-progress > span {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--gold-500);
  transform-origin: 0 50%;
  transform: scaleX(0);
}
.carousel.is-playing .carousel-progress > span {
  animation: carousel-tick var(--autoplay-ms, 6000ms) linear infinite;
}
.carousel:not(.is-playing) .carousel-progress { opacity: 0; }

@keyframes carousel-tick {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

@media (prefers-reduced-motion: reduce) {
  .carousel.is-playing .carousel-progress > span { animation: none; }
  .carousel-progress { display: none; }
}

/* =========================================================================
   Service and tool detail pages
   ========================================================================= */
.detail-head { margin-bottom: var(--space-10); max-width: var(--measure-wide); }
.detail-icon {
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  margin-bottom: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--brand-50);
  color: var(--brand-600);
}
.detail-badges { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-bottom: var(--space-3); }
.detail-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-6); }
@media (max-width: 460px) {
  .detail-actions { flex-direction: column; align-items: stretch; }
  .detail-actions .btn { width: 100%; }
}

/* ---- how-it-works steps ---- */
.step-list {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  list-style: none;
  counter-reset: step;
}
.step-item {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.step-num {
  display: grid;
  place-items: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-pill);
  background: var(--brand-600);
  color: var(--ink-0);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
}
.step-name { display: block; font-weight: var(--weight-semibold); color: var(--text); }
.step-text { display: block; margin-top: var(--space-1); font-size: var(--text-base);
             line-height: var(--leading-normal); color: var(--text-muted); }

/* ---- FAQ ---- */
.faq-list { display: grid; gap: var(--space-3); max-width: var(--measure-wide); }
.faq-item {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  overflow: hidden;
}
.faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  font-weight: var(--weight-semibold);
  color: var(--text);
  cursor: pointer;
  list-style: none;
}
.faq-question::-webkit-details-marker { display: none; }
.faq-question::after {
  content: "+";
  flex: none;
  font-size: var(--text-lg);
  color: var(--text-brand);
  transition: transform var(--duration-fast) var(--ease-out);
}
.faq-item[open] .faq-question::after { transform: rotate(45deg); }
.faq-answer {
  padding: 0 var(--space-5) var(--space-5);
  font-size: var(--text-base);
  line-height: var(--leading-loose);
  color: var(--text-muted);
}

/* =========================================================================
   Calculator panels
   ========================================================================= */
.tool-panel {
  padding: var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: var(--shadow-md);
}
.tool-panel-head { margin-bottom: var(--space-6); }

/* Segmented control */
.seg {
  display: inline-flex;
  padding: 3px;
  margin-bottom: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--bg-sunken);
}
.seg-btn {
  padding: var(--space-2) var(--space-5);
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--text-muted);
  transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.seg-btn.is-active { background: var(--surface); color: var(--text-brand); box-shadow: var(--shadow-sm); }

.calc-grid {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}
.calc-col-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  color: var(--text);
}

.calc-row { display: grid; gap: var(--space-2); margin-bottom: var(--space-3); }
.calc-row-label { font-size: var(--text-base); color: var(--text-muted); }
.calc-row-select { width: 100%; }

.calc-courses { display: grid; gap: var(--space-3); margin-bottom: var(--space-4); }
.calc-course {
  display: grid;
  gap: var(--space-2);
  grid-template-columns: minmax(0, 2fr) 5.5rem 6rem 40px;
  align-items: center;
}
@media (max-width: 640px) {
  .calc-course { grid-template-columns: minmax(0, 1fr) 4.5rem 5rem 36px; }
}

.calc-prev {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}

/* ---- result ---- */
.calc-result {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  align-items: center;
  margin-top: var(--space-6);
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  background: var(--gradient-brand);
  color: var(--ink-0);
  box-shadow: var(--shadow-brand);
}
@media (max-width: 640px) { .calc-result { grid-template-columns: minmax(0, 1fr); } }

.calc-result-figure { text-align: center; }
.calc-result-value {
  display: block;
  font-size: clamp(2.5rem, 6vw + 1rem, 3.75rem);
  font-weight: var(--weight-black);
  line-height: 1;
  color: var(--ink-0);
  font-variant-numeric: tabular-nums;
}
.calc-result-label {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.8);
}
.calc-result-note { font-size: var(--text-base); line-height: var(--leading-normal); color: rgba(255, 255, 255, 0.92); }

.calc-breakdown { list-style: none; display: grid; gap: var(--space-1); margin-top: var(--space-4); }
.calc-breakdown li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-1) 0;
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.85);
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}
.calc-breakdown li:last-child { border-bottom: 0; }
.calc-breakdown strong { color: var(--ink-0); }

.calc-disclaimer {
  margin-top: var(--space-5);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-subtle);
}

/* Fact list on a scholarship page reuses the breakdown rows, but on a light
   surface rather than inside the gradient result panel. */
.scholarship-facts-list { margin-top: 0; max-width: var(--measure-wide); }
.scholarship-facts-list li { color: var(--text-muted); border-bottom-color: var(--border); }
.scholarship-facts-list strong { color: var(--text); }

/* =========================================================================
   News & Blog section furniture
   ========================================================================= */

/* Tinted rounded badge in front of a section title. */
.section-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--brand-50);
  color: var(--brand-600);
}
@media (max-width: 640px) {
  .section-icon { width: 34px; height: 34px; }
}

/* The "All news →" link keeps its arrow on the same line and nudges it on
   hover, which is the only motion this control needs. */
.section-more {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  white-space: nowrap;
}
.section-more svg { transition: transform var(--duration-fast) var(--ease-out); }
.section-more:hover svg { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) {
  .section-more:hover svg { transform: none; }
}

/* Card meta: date and read time, each with its own glyph. */
.post-meta-item { display: inline-flex; align-items: center; gap: var(--space-2); }
.post-meta-item svg { color: var(--text-subtle); flex: none; }
.post-meta-dot { color: var(--border-strong); }

/* =========================================================================
   Trust strip
   Four columns on a sunken panel, divided by hairlines. Collapses to two
   columns and then one, dropping the dividers rather than leaving orphaned
   vertical rules between stacked rows.
   ========================================================================= */
.trust-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-6);
  /* No top margin: this is its own section now, so the standard
     .home-block + .home-block rhythm handles the spacing above it. */
  padding: var(--space-6) var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--bg-sunken);
  list-style: none;
}

.trust-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding-inline: var(--space-4);
  border-left: 1px solid var(--border);
}
.trust-item:first-child { border-left: 0; }

.trust-icon { flex: none; display: grid; place-items: center; margin-top: 2px; }

/* One hue per pillar, so the row reads as four distinct ideas rather than a
   block of identical marks. Decorative only - the text carries the meaning. */
.trust-icon[data-tone="trust"]  { color: var(--brand-500); }
.trust-icon[data-tone="speed"]  { color: var(--gold-500); }
.trust-icon[data-tone="expert"] { color: var(--success-600); }
.trust-icon[data-tone="talk"]   { color: var(--warning-500); }

.trust-title {
  display: block;
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  color: var(--text);
}
.trust-text {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-muted);
}

@media (max-width: 900px) {
  .trust-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-5); }
  .trust-item:nth-child(odd) { border-left: 0; }
}
@media (max-width: 560px) {
  .trust-strip { grid-template-columns: minmax(0, 1fr); padding: var(--space-5); }
  .trust-item { border-left: 0; padding-inline: 0; }
}

/* The search button matches its pill container. A 10px-radius button sitting
   inside a fully rounded field is the detail that makes the whole control look
   unfinished. */
.home-search .btn {
  border-radius: var(--radius-pill);
  padding-inline: var(--space-5);
  flex: none;
}

/* =========================================================================
   Tile — the shared service / tool card
   ========================================================================= */
.tile {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "icon head arrow"
    "text text arrow";
  column-gap: var(--space-4);
  row-gap: var(--space-3);
  align-items: start;
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out);
}

/* A brand hairline that wipes across the top edge on hover. Cheaper to read
   than a colour change on the whole card, and it points the eye at the arrow. */
.tile::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 100%;
  height: 3px;
  background: var(--gradient-brand);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform var(--duration-slow) var(--ease-out);
}

.tile:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--brand-200);
}
.tile:hover::before { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .tile, .tile::before { transition: none; }
  .tile:hover { transform: none; }
}

/* ---- icon: deep navy plate, white glyph ---- */
.tile-icon {
  grid-area: icon;
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  flex: none;
  border-radius: var(--radius-md);
  background: linear-gradient(140deg, var(--brand-500) 0%, var(--brand-700) 100%);
  color: var(--ink-0);
  box-shadow: 0 6px 16px rgba(55, 58, 121, 0.30),
              inset 0 1px 0 rgba(255, 255, 255, 0.22);
  transition: transform var(--duration-base) var(--ease-spring),
              box-shadow var(--duration-base) var(--ease-out);
}
.tile:hover .tile-icon {
  transform: translateY(-1px) scale(1.06);
  box-shadow: 0 10px 22px rgba(55, 58, 121, 0.38),
              inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
@media (prefers-reduced-motion: reduce) {
  .tile-icon, .tile:hover .tile-icon { transition: none; transform: none; }
}

/* ---- title and badge ---- */
.tile-head {
  grid-area: head;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  min-width: 0;
  padding-top: var(--space-1);
}

.tile-title {
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-snug);
  color: var(--text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-clamp: 2;
  overflow: hidden;
  /* Two lines are reserved whether or not the title needs both, so a tile is
     the same height everywhere it appears. Without this, a section whose
     titles happen to be short sits shorter than the one above it and the two
     stop reading as one system. */
  min-height: calc(2 * var(--leading-snug) * 1em);
}
.tile:hover .tile-title { color: var(--text-brand); }

.tile-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem var(--space-2);
  border-radius: var(--radius-xs);
  font-size: 0.6875rem;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
}
.tile-badge[data-tier="FREE"]    { color: var(--tier-free-fg);    background: var(--tier-free-bg); }
.tile-badge[data-tier="TRIAL"]   { color: var(--tier-trial-fg);   background: var(--tier-trial-bg); }
.tile-badge[data-tier="PREMIUM"] { color: var(--tier-premium-fg); background: var(--tier-premium-bg); }
.tile-badge[data-tier="ACTION"]  { color: var(--brand-600);       background: var(--brand-50); }

/* ---- description ---- */
.tile-text {
  grid-area: text;
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-clamp: 2;
  overflow: hidden;
  min-height: calc(2 * var(--leading-normal) * 1em);
}

/* ---- arrow ---- */
.tile-arrow {
  grid-area: arrow;
  align-self: center;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--bg-sunken);
  color: var(--text-brand);
  transition: transform var(--duration-base) var(--ease-out),
              background var(--duration-base) var(--ease-out),
              color var(--duration-base) var(--ease-out);
}
.tile:hover .tile-arrow {
  background: var(--brand-600);
  color: var(--ink-0);
  transform: translateX(3px);
}
@media (prefers-reduced-motion: reduce) {
  .tile:hover .tile-arrow { transform: none; }
}

/* Keyboard users get the same affordance as the mouse. */
.tile:focus-visible { outline: none; box-shadow: var(--shadow-lg), var(--focus-ring); }

@media (max-width: 520px) {
  .tile { padding: var(--space-4); column-gap: var(--space-3); }
  .tile-icon { width: 46px; height: 46px; }
  .tile-arrow { width: 30px; height: 30px; }
}

/* A plain grid of tiles, for the directory pages. */
.tile-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
}

/* -------------------------------------------------------------------------
   Carousel containment
   A belt-and-braces bound on the carousel itself. .main-content is now
   constrained, but a carousel dropped into any other container would blow the
   same hole: its track is a nowrap flex row whose intrinsic width is the sum
   of every slide, and that width propagates up through block ancestors until
   something stops it. The viewport's own overflow-x:auto cannot clip anything
   while its parent has already been stretched to fit.
   ------------------------------------------------------------------------- */
.carousel,
.carousel-viewport { max-width: 100%; }

/* On a narrow phone the Search button and the field compete for the same row.
   Letting the button shrink to its label keeps the input wide enough that the
   placeholder is not clipped at 320px, which is the narrowest width still in
   real use. */
@media (max-width: 420px) {
  .home-search input { min-width: 0; }
  .home-search .btn { padding-inline: var(--space-4); flex-shrink: 0; }
}

/* At 320px - the narrowest width still in real use - the Search button and the
   field compete for one row and the placeholder was clipped. Measured: a
   compact button gives the input 151px against the 143px the placeholder
   needs. */
@media (max-width: 380px) {
  .home-search .btn { padding-inline: 10px; font-size: var(--text-sm); }
}

/* The hero search field uses `font: inherit`, and the `font` shorthand resets
   font-size — so it lands back at 15px and re-introduces the iOS zoom-on-focus
   bug that shell.css fixes for every other field. site.css loads after
   shell.css, so the correction has to live here to win on order. */
@media (max-width: 768px) {
  .home-search input { font-size: 16px; }
}

/* A long label in a .btn-lg (32px of padding each side) is wider than a 320px
   phone. Measured on /how-it-works: 290px of button pushed the document to
   322px. Buttons may shrink and wrap rather than force the page sideways. */
@media (max-width: 420px) {
  .btn-lg {
    padding-inline: var(--space-5);
    max-width: 100%;
    white-space: normal;
  }
}
