/* ==========================================================================
   GrinHub design system
   --------------------------------------------------------------------------
   Palette comes from the brand flyer and the teal reference swatches:
   dark teal and rust lead, over cream. Petrol carries the footer and the
   dark surfaces; abyss is the dark-mode ground.

   Depth, not outlines: raised things take a soft drop shadow, recessed things
   an inward one. Hairline borders read as cheap and accumulate across a page.

   COLOUR DISCIPLINE — at most three colours carry any single page:
   the background, the ink, and ONE of brand/accent doing the emphasis.
   Pages reference semantic tokens (--bg, --ink, --brand …) and never the raw
   names below, so light and dark stay in step and a repaint is one edit here.
   ========================================================================== */

:root {
  /* Raw brand colours — do not use directly in page CSS. */
  --c-teal:    #145055;
  --c-teal-lo: #1d6b70;
  --c-teal-hi: #4da8ad;
  --c-rust:    #c25a28;
  --c-rust-lo: #a44a1f;
  --c-rust-hi: #e07a45;
  --c-cream:   #f7f0e6;
  --c-cream-2: #efe5d7;
  /* From the teal reference swatches. */
  --c-lagoon:   #1a5f78;
  --c-peacock:  #0d6b6b;
  --c-atlantic: #14425a;
  --c-atlantic-deep: #0d3040;
  /* Past abyss and out of the blues entirely. Reads as black, but a hair of
     green in it keeps it related to the teal rather than dead neutral, and it
     avoids the halation pure #000 causes behind light text. */
  --c-midnight: #0a0e0f;
  --c-charcoal: #14181a;
  --c-charcoal-2: #1c2123;
  --c-petrol:   #14505c;
  --c-abyss:    #0f1b33;

  /* Semantic tokens — light. */
  --bg:         var(--c-cream);
  --bg-soft:    var(--c-cream-2);
  --surface:    #fffdfa;
  --ink:        #1a2422;
  --muted:      #5f6b68;
  --line:       #ded2c2;
  --brand:      var(--c-teal);
  --brand-hover:var(--c-teal-lo);
  --on-brand:   #ffffff;
  --accent:     var(--c-rust);
  --accent-hover: var(--c-rust-lo);
  --on-accent:  #ffffff;
  --ok:         #1a7f52;
  --err:        #b3261e;
  --focus:      var(--c-teal-lo);
  /* The wordmark sits in charcoal rather than the body ink, so it holds its
     own against the teal pin; in dark mode it goes plain white. */
  --wordmark:   #33393b;

  --radius:   12px;
  --radius-s: 8px;
  --wrap:     1100px;
  /* One gutter for the whole site, so nothing sits against the screen edge.
     Wider than the usual 20px on a phone, where a line of text touching the
     bezel is the thing that makes a page feel cramped. */
  --gutter: clamp(24px, 4vw, 32px);

  /* Depth instead of outlines. Raised things catch light from above; recessed
     things — inputs, wells — take a shadow on their inner top edge. Hairline
     borders read as cheap at this size, and stack up visually across a page. */
  --shadow:      0 1px 2px rgba(15,27,51,.04), 0 6px 20px rgba(15,27,51,.06);
  --shadow-lift: 0 2px 4px rgba(15,27,51,.05), 0 14px 34px rgba(15,27,51,.10);
  --shadow-well: inset 0 1px 3px rgba(20,32,30,.10), inset 0 0 0 1px rgba(20,32,30,.05);
  --shadow-well-focus: inset 0 1px 2px rgba(20,32,30,.06);
  /* Kept for the few places a real dividing line is still the right answer. */
  --hairline: color-mix(in srgb, var(--line) 60%, transparent);

  --font-display: 'Lora', Georgia, 'Times New Roman', serif;
  --font-text: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  --ease: cubic-bezier(.22, .61, .36, 1);
  --t-fast: .18s;
  --t-med: .34s;
}

/* Dark tokens. Defined twice on purpose: once for viewers whose system is
   dark and who have not chosen, once for an explicit choice, so the toggle
   wins in both directions. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:         var(--c-midnight);
    --bg-soft:    var(--c-charcoal);
    --surface:    var(--c-charcoal-2);
    --ink:        #ece4d8;
    --muted:      #98a2a3;
    --line:       #2b3133;
    --brand:      var(--c-teal-hi);
    --brand-hover:#6cc0c4;
    --on-brand:   #06201f;
    --accent:     var(--c-rust-hi);
    --accent-hover: #ef8d5a;
    --on-accent:  #2a1206;
    --focus:      var(--c-teal-hi);
    --wordmark:   #ffffff;
    --shadow:      0 1px 2px rgba(0,0,0,.30), 0 6px 20px rgba(0,0,0,.34);
    --shadow-lift: 0 2px 6px rgba(0,0,0,.36), 0 16px 38px rgba(0,0,0,.44);
    --shadow-well: inset 0 1px 3px rgba(0,0,0,.42), inset 0 0 0 1px rgba(255,255,255,.05);
    --shadow-well-focus: inset 0 1px 2px rgba(0,0,0,.3);
  }
}

:root[data-theme="dark"] {
  --bg:         var(--c-midnight);
  --bg-soft:    var(--c-charcoal);
  --surface:    var(--c-charcoal-2);
  --ink:        #ece4d8;
  --muted:      #98a2a3;
  --line:       #2b3133;
  --brand:      var(--c-teal-hi);
  --brand-hover:#6cc0c4;
  --on-brand:   #06201f;
  --accent:     var(--c-rust-hi);
  --accent-hover: #ef8d5a;
  --on-accent:  #2a1206;
  --focus:      var(--c-teal-hi);
    --wordmark:   #ffffff;
  --shadow:      0 1px 2px rgba(0,0,0,.30), 0 6px 20px rgba(0,0,0,.34);
    --shadow-lift: 0 2px 6px rgba(0,0,0,.36), 0 16px 38px rgba(0,0,0,.44);
    --shadow-well: inset 0 1px 3px rgba(0,0,0,.42), inset 0 0 0 1px rgba(255,255,255,.05);
    --shadow-well-focus: inset 0 1px 2px rgba(0,0,0,.3);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-text);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.65;
  -webkit-text-size-adjust: 100%;
  transition: background var(--t-med) var(--ease), color var(--t-med) var(--ease);
}

/* Headings sit at 500. Lora is a text serif built for calm, even colour
   rather than display drama, and 700 reads as shouting on a phone, where a
   heading fills most of the view. */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.22;
  letter-spacing: -.008em;
  margin: 0 0 .5em;
}
/* Headings carry the teal. It was previously confined to the hero wash, small
   icons and link text, so the brand colour barely registered on a page. */
h1 { font-size: clamp(1.75rem, 4.6vw, 3.2rem); color: var(--brand); }
h2 { font-size: clamp(1.3rem, 3vw, 2.1rem); color: var(--brand); }
/* h3 used to switch to the body sans-serif, which meant a page with h1/h2/h3
   all visible at once was speaking in two different typefaces. It now stays
   in the display family at a size and weight calm enough for a card title. */
h3 { font-size: 1.05rem; font-weight: 500; letter-spacing: -.004em; }
p  { margin: 0 0 1em; }
a  { color: var(--brand); }

/* Phones: shorter measure, so lines need more air and less weight. */
@media (max-width: 620px) {
  body { line-height: 1.72; font-size: .97rem; }
  h1 { letter-spacing: -.005em; line-height: 1.22; }
  h2 { line-height: 1.25; }
  .lead { font-size: 1rem; }
  .hero p { font-size: 1rem; }
}

img { max-width: 100%; }

/* Nothing wider than the viewport should ever force the whole page to
   scroll sideways — a form control with a long, dynamic content-based
   minimum width (e.g. a <select> full of owner-typed role names) is the
   usual culprit, and flex-wrap alone doesn't stop it without this. */
body { overflow-x: hidden; }
input, select, textarea, button { max-width: 100%; }

.wrap   { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }
.narrow { max-width: 680px; }

/* ---------- header ---------- */

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px var(--gutter);
  box-shadow: 0 1px 0 var(--hairline), 0 4px 18px rgba(15,27,51,.045);
  position: sticky;
  top: 0;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  z-index: 40;
}

/* Brand lock-up: the mark plus the wordmark. The wordmark was missing before,
   which is why nothing but the pin showed in the bar. */
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--wordmark); }
.brand-logo { height: 34px; width: auto; display: block; transition: filter var(--t-med) var(--ease); }
.brand-name { font-family: var(--font-display); font-size: 1.18rem; font-weight: 600; letter-spacing: -.01em;
              line-height: 1; color: var(--wordmark); transition: color var(--t-med) var(--ease); }
/* line-height is explicit, not inherited. Left to the body default (1.65,
   1.72 on a phone) it pads a lot of empty space above and below six words at
   .58rem, and the tagline reads as floating away from the name above it. */
.brand-tag  { display: block; font-family: var(--font-text); font-size: .58rem; font-weight: 600;
              line-height: 1.3; letter-spacing: .12em; text-transform: uppercase;
              color: var(--brand); margin-top: 3px; }

/* Bleach the teal pin to white so it reads on the dark bar. One asset, both modes. */
:root[data-theme="dark"] .brand-logo { filter: brightness(0) invert(1); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-logo { filter: brightness(0) invert(1); }
}

header img:not(.brand-logo) { height: 34px; width: auto; display: block; }

header nav { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
header nav a { text-decoration: none; font-weight: 600; font-size: .94rem; color: var(--ink); position: relative; }
header nav a:not(.btn)::after {
  content: ''; position: absolute; left: 0; right: 100%; bottom: -4px; height: 2px;
  background: var(--accent); transition: right var(--t-fast) var(--ease);
}
header nav a:not(.btn):hover::after { right: 0; }

/* Mobile navigation. The toggle is a checkbox so the menu works without JS. */
.nav-toggle, .nav-toggle-label { display: none; }

@media (max-width: 820px) {
  .nav-toggle-label {
    display: block; cursor: pointer; padding: 8px; margin-left: auto;
    background: none; border: 0; color: var(--ink);
  }
  .nav-toggle-label span,
  .nav-toggle-label span::before,
  .nav-toggle-label span::after {
    display: block; width: 22px; height: 2px; background: currentColor;
    border-radius: 2px; transition: transform var(--t-fast) var(--ease);
  }
  .nav-toggle-label span::before { content: ''; transform: translateY(-7px); }
  .nav-toggle-label span::after  { content: ''; transform: translateY(5px); }

  header nav {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--surface); border-bottom: 1px solid var(--hairline);
    max-height: 0; overflow: hidden; transition: max-height var(--t-med) var(--ease);
  }
  header nav a { padding: 14px var(--gutter); border-top: 1px solid var(--hairline); }
  header nav a.btn { margin: 14px var(--gutter); text-align: center; }
  .nav-toggle:checked ~ nav { max-height: 60vh; }
}

/* ---------- theme toggle ---------- */

/* ---------- floating actions ----------
   The theme toggle and the back-to-top button live here, bottom-right on
   every page, deliberately outside the header: a toolbar button competes
   with navigation, and this reads as a small courtesy instead. Both share
   .float-btn for shape; .theme-toggle keeps only what is specific to it. */

.float-actions {
  position: fixed;
  right: clamp(14px, 3vw, 22px);
  bottom: calc(clamp(14px, 3vw, 22px) + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.float-btn {
  display: grid; place-items: center;
  width: 34px; height: 34px; padding: 0;
  border: 0; border-radius: 50%;
  background: var(--surface); color: var(--ink);
  box-shadow: var(--shadow-lift);
  cursor: pointer;
  transition: box-shadow var(--t-fast) var(--ease), transform var(--t-fast) var(--ease),
              opacity var(--t-fast) var(--ease);
}
.float-btn:hover { box-shadow: var(--shadow-lift), inset 0 0 0 1.5px var(--brand); transform: translateY(-2px); }
.float-btn svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.9; }

.theme-toggle:hover { transform: rotate(-16deg) translateY(-2px); }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun  { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-sun  { display: none; }
  :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: block; }
}

/* Present in the markup on every page from the first paint, so there is no
   flash of an unstyled button; invisible and inert until app.js adds .show
   once a visitor has scrolled about three quarters of the way down. */
.back-to-top {
  opacity: 0; transform: translateY(8px) scale(.82);
  pointer-events: none;
}
.back-to-top.show {
  opacity: 1; transform: none;
  pointer-events: auto;
}
@media (prefers-reduced-motion: reduce) {
  .back-to-top { transition: opacity var(--t-fast) linear; transform: none; }
  .float-btn:hover, .theme-toggle:hover { transform: none; }
}

/* ---------- buttons ---------- */

.btn {
  display: inline-block;
  padding: 13px 26px;
  border-radius: var(--radius-s);
  background: var(--brand);
  color: var(--on-brand) !important;
  text-decoration: none;
  font-weight: 600;
  border: 0;
  cursor: pointer;
  font-size: 1rem;
  font-family: inherit;
  transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
}
.btn:hover { background: var(--brand-hover); transform: translateY(-2px); box-shadow: var(--shadow); }
.btn:active { transform: translateY(0); }

/* Accent button. .btn-gold is kept as an alias so existing markup keeps working.
   Hovering turns it from rust to petrol rather than to a darker rust — the two
   brand colours trading places reads as deliberate, and it is a clearer signal
   than a shade change. */
.btn-accent, .btn-gold { background: var(--accent); color: var(--on-accent) !important; }
.btn-accent:hover, .btn-gold:hover {
  background: var(--c-petrol);
  color: #fff !important;
}
:root[data-theme="dark"] .btn-accent:hover,
:root[data-theme="dark"] .btn-gold:hover { background: var(--c-teal-hi); color: #06201f !important; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn-accent:hover,
  :root:not([data-theme="light"]) .btn-gold:hover { background: var(--c-teal-hi); color: #06201f !important; }
}

.btn-ghost {
  background: transparent; color: var(--ink) !important;
  box-shadow: inset 0 0 0 1.5px var(--hairline);
}
.btn-ghost:hover { background: var(--bg-soft); box-shadow: inset 0 0 0 1.5px var(--brand); }

.btn[disabled] { opacity: .5; cursor: not-allowed; transform: none; box-shadow: none; }
.btn-block { display: block; width: 100%; text-align: center; }

/* ---------- hero ---------- */

.hero {
  position: relative;
  background: var(--c-teal);
  color: #fff;
  padding: clamp(56px, 10vw, 120px) 0;
  overflow: hidden;
  isolation: isolate;
}
/* Photographic hero: the image sits behind a wash dark enough to keep text
   legible whatever the photo does. */
.hero-img { position: absolute; inset: 0; z-index: -2; overflow: hidden; }
/* Slow push in on the photograph only. The wash above it does not move, so the
   text stays put and nothing reflows — the image alone drifts closer. */
.hero-img img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform-origin: 52% 45%;
  animation: hero-zoom 26s var(--ease) forwards;
}
@keyframes hero-zoom {
  from { transform: scale(1); }
  to   { transform: scale(1.09); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-img img { animation: none; }
}
/* The wash is black in light mode and teal in dark. Inverted deliberately:
   against a cream page a black band is the stronger frame, and against a
   near-black page the teal is what stops the hero disappearing into the
   background. */
.hero::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(105deg,
    rgba(8, 11, 12, .90) 0%,
    rgba(8, 11, 12, .70) 52%,
    rgba(8, 11, 12, .46) 100%);
}

:root[data-theme="dark"] .hero::before {
  background: linear-gradient(105deg,
    color-mix(in srgb, var(--c-teal) 92%, transparent) 0%,
    color-mix(in srgb, var(--c-petrol) 80%, transparent) 55%,
    color-mix(in srgb, var(--c-abyss) 66%, transparent) 100%);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .hero::before {
    background: linear-gradient(105deg,
      color-mix(in srgb, var(--c-teal) 92%, transparent) 0%,
      color-mix(in srgb, var(--c-petrol) 80%, transparent) 55%,
      color-mix(in srgb, var(--c-abyss) 66%, transparent) 100%);
  }
}
.hero h1 { color: #fff; max-width: 16ch; }
.hero p  { max-width: 56ch; font-size: 1.1rem; color: rgba(255,255,255,.92); }
.hero .actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 28px; }
.hero .eyebrow {
  font-size: .72rem; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--c-rust-hi); margin-bottom: 14px;
}
.hero-sm { padding: clamp(40px, 7vw, 76px) 0; }
.hero-sm h1 { max-width: 22ch; }

/* ---------- sections ---------- */

section { padding: clamp(44px, 7vw, 84px) 0; }
/* A teal wash rather than a darker cream, so alternating sections read as
   brand rather than as a shade of the paper. */
section.soft { background: color-mix(in srgb, var(--brand) 7%, var(--bg-soft)); }
.lead { color: var(--muted); max-width: 62ch; font-size: 1.05rem; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 22px;
  margin-top: 34px;
}

.card {
  background: var(--surface);
  border: 0;
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: var(--shadow);
  transition: transform var(--t-med) var(--ease), box-shadow var(--t-med) var(--ease),
              border-color var(--t-med) var(--ease);
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); }
.card h3 { margin-bottom: .4em; }
.card p { color: var(--muted); font-size: .95rem; margin-bottom: .75em; }
.card .tags { font-size: .85rem; color: var(--muted); }

/* Staff dashboard shell — informational tiles, not links, so no hover-lift. */
.dash-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.dash-role {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--brand);
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  padding: 3px 10px;
  border-radius: 999px;
  margin-left: 10px;
  vertical-align: middle;
}
.dash-card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: var(--shadow);
}
.dash-card h3 { margin-bottom: .3em; }
.dash-card .soon { color: var(--muted); font-size: .92rem; margin: 0; }

.dash-owed { font-size: 1.9rem; font-weight: 700; margin: 2px 0 16px; font-variant-numeric: tabular-nums; }
.money-form { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.money-form select { flex: 0 0 110px; }
.money-form input { flex: 1 1 200px; }
/* Every dashboard list row — payments, tasks, checklists, invoices,
   codes, news, classes — is one of these. wrap is load-bearing: a row
   with a status pill and two or three action buttons has no room to
   stay on one line once the viewport is a phone's, and without it the
   row overflows sideways instead of dropping the buttons to a second
   line. The first child is always the row's own label/description, so
   it is the one allowed to actually shrink and wrap its text rather
   than pushing everything else off screen. */
.money-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 6px 10px;
  padding: 10px 0;
  border-top: 1px solid var(--hairline);
  font-size: .9rem;
  font-variant-numeric: tabular-nums;
}
.money-row:first-child { border-top: 0; }
.money-row > *:first-child { flex: 1 1 200px; min-width: 0; overflow-wrap: break-word; }
.money-row .money-when { color: var(--muted); font-size: .82rem; }
.status-pill {
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding: 2px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.status-pill.pending, .status-pill.planned, .status-pill.received, .status-pill.reviewing {
  color: var(--brand); background: color-mix(in srgb, var(--brand) 14%, transparent);
}
.status-pill.paid, .status-pill.held, .status-pill.interviewing, .status-pill.offered {
  color: var(--ok); background: color-mix(in srgb, var(--ok) 14%, transparent);
}
.status-pill.declined, .status-pill.cancelled, .status-pill.withdrawn {
  color: var(--err); background: color-mix(in srgb, var(--err) 14%, transparent);
}
.status-pill.interviewed {
  color: var(--ok); background: color-mix(in srgb, var(--ok) 14%, transparent);
}

.app-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0 16px; }
.app-tab {
  border: 1px solid var(--hairline, #ddd);
  background: transparent;
  color: var(--ink);
  border-radius: 999px;
  padding: 5px 14px;
  font-size: .85rem;
  cursor: pointer;
}
.app-tab.active {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-accent);
}

.steps { counter-reset: step; display: grid; gap: 20px; margin-top: 30px; }
.steps li { list-style: none; display: flex; gap: 16px; align-items: flex-start; }
.steps li::before {
  counter-increment: step;
  content: counter(step);
  flex: 0 0 32px; height: 32px;
  border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  font-weight: 700; display: grid; place-items: center; font-size: .9rem;
}
.steps strong { display: block; }
.steps span { color: var(--muted); font-size: .95rem; }

/* ---------- forms ---------- */

.form-section { padding: clamp(32px, 6vw, 60px) 0; }

form { display: grid; gap: 18px; }

/* Card-per-question, in the manner of a well-made form: generous target
   areas, one clear focus state, no visual noise between fields. */
.field { display: grid; gap: 7px; }
.field label { font-weight: 600; font-size: .93rem; }
.field .hint { font-size: .85rem; color: var(--muted); }

input, select, textarea {
  width: 100%;
  padding: 13px 15px;
  border: 0;
  border-radius: var(--radius-s);
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  box-shadow: var(--shadow-well);
  transition: box-shadow var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
input::placeholder, textarea::placeholder { color: color-mix(in srgb, var(--muted) 70%, transparent); }
input:focus, select:focus, textarea:focus {
  outline: none;
  box-shadow: var(--shadow-well-focus),
              0 0 0 3px color-mix(in srgb, var(--focus) 26%, transparent);
}
textarea { min-height: 130px; resize: vertical; }

.row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 560px) { .row { grid-template-columns: 1fr; } }

.check { display: flex; gap: 11px; align-items: flex-start; font-size: .93rem; }
.check input { width: auto; margin-top: 4px; flex: 0 0 auto; accent-color: var(--brand); }

fieldset { border: 0; border-radius: var(--radius); padding: 20px; margin: 0; background: var(--surface); box-shadow: var(--shadow); }
legend { font-weight: 600; padding: 0 8px; font-size: .95rem; }

/* ---------- price panel ---------- */

.price-panel { background: var(--bg-soft); border: 0; border-radius: var(--radius); padding: 20px; box-shadow: var(--shadow-well); }
.price-row { display: flex; justify-content: space-between; gap: 12px; font-size: .95rem; padding: 3px 0; }
.price-row.total { border-top: 1px solid var(--hairline); margin-top: 8px; padding-top: 10px; font-weight: 700; font-size: 1.15rem; }
.price-note { font-size: .82rem; color: var(--muted); margin: 10px 0 0; }

/* What the course consists of. Sits directly under the total, because the
   hours are what make the figure judgeable rather than arbitrary. */
.price-hours {
  font-size: .88rem; font-weight: 600; color: var(--brand);
  margin: 8px 0 0; padding-top: 8px;
  border-top: 1px solid var(--hairline);
}

/* The same line under the programme picker, shown as soon as one is chosen. */
.course-note {
  display: flex; align-items: center; gap: 8px;
  font-size: .9rem; font-weight: 600; color: var(--brand);
  background: color-mix(in srgb, var(--brand) 8%, var(--surface));
  border-radius: var(--radius-s);
  padding: 10px 14px;
  margin: -6px 0 18px;
}
.course-note::before {
  content: ''; flex: 0 0 auto;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
}

/* ---------- feedback ---------- */

.msg { padding: 13px 15px; border-radius: var(--radius-s); font-size: .95rem; display: none; }
.msg.show { display: block; }
.msg.error { background: color-mix(in srgb, var(--err) 12%, var(--surface)); color: var(--err); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--err) 26%, transparent); }
.msg.ok    { background: color-mix(in srgb, var(--ok) 12%, var(--surface));  color: var(--ok);  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ok) 26%, transparent); }
.msg.info  { background: color-mix(in srgb, var(--brand) 12%, var(--surface)); color: var(--brand); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand) 26%, transparent); }

/* A floating version of .msg for inline dashboard actions that have no
   nearby form to show a result in — replaces native alert(), which
   blocks the whole tab until dismissed. */
.msg.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 999; max-width: 90vw; width: 420px; box-shadow: var(--shadow); }

/* ---------- status ---------- */

.status-card { border: 0; border-radius: var(--radius); padding: 26px; background: var(--surface); box-shadow: var(--shadow); }
.status-badge { display: inline-block; padding: 5px 13px; border-radius: 999px; font-size: .82rem; font-weight: 700; letter-spacing: .02em; }
.status-badge.pending { background: color-mix(in srgb, var(--accent) 18%, var(--surface)); color: var(--accent); }
.status-badge.settled { background: color-mix(in srgb, var(--ok) 15%, var(--surface)); color: var(--ok); }
.id-display {
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 1.6rem; font-weight: 700; letter-spacing: .06em;
  background: var(--bg-soft); border: 0;
  border-radius: var(--radius); padding: 18px; text-align: center; margin: 16px 0; color: var(--brand);
  box-shadow: var(--shadow-well);
}
dl.detail { display: grid; grid-template-columns: auto 1fr; gap: 8px 20px; font-size: .95rem; margin: 0; }
dl.detail dt { color: var(--muted); }
dl.detail dd { margin: 0; font-weight: 600; }

/* ---------- legal ---------- */

/* A field the form is complaining about. Colour alone would not reach
   anybody who cannot see it, so the attribute carries the meaning and this
   only draws it. */
[aria-invalid="true"] {
  box-shadow: var(--shadow-well), 0 0 0 2px var(--accent);
}

/* Legal pages carry no header or footer, so this link is the only chrome. */
.legal-back {
  display: inline-flex; align-items: center; gap: 8px;
  margin: clamp(20px, 4vw, 34px) 0 0 var(--gutter);
  color: var(--muted); font-weight: 600; font-size: .95rem; text-decoration: none;
}
.legal-back svg {
  width: 18px; height: 18px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  transition: transform .2s ease;
}
.legal-back:hover { color: var(--brand); }
.legal-back:hover svg { transform: translateX(-3px); }

.legal { max-width: 760px; }
.legal h1 { font-size: clamp(1.7rem, 4vw, 2.3rem); margin-bottom: 12px; }
.legal h2 { margin-top: 2em; font-size: 1.3rem; }
.legal h3 { margin-top: 1.5em; }
.legal ul { padding-left: 1.25em; }
.legal li { margin-bottom: .4em; }
.doc-meta { color: var(--muted); font-size: .9rem; border-bottom: 1px solid var(--hairline); padding-bottom: 14px; margin-bottom: 24px; }
.notice { background: var(--bg-soft); border: 0; border-radius: var(--radius); padding: 14px 16px; font-size: .92rem; box-shadow: var(--shadow-well); }

/* ---------- links that must not underline (contact, socials) ---------- */

.plain-link { text-decoration: none; color: inherit; display: inline-flex; align-items: center; gap: 9px; }
.plain-link:hover { color: var(--brand); }
.plain-link svg { width: 19px; height: 19px; flex: 0 0 auto; }

/* Bare marks, no discs. The circles read as buttons and crowded the card;
   the icon alone is enough, and it can then move on hover. */
.social-row { display: flex; gap: 20px; flex-wrap: wrap; align-items: center; }

.social-row a {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--ink); text-decoration: none;
  font-weight: 600; font-size: .94rem;
  transition: color var(--t-fast) var(--ease);
}
.social-row svg {
  width: 21px; height: 21px; flex: 0 0 auto;
  transition: transform .32s var(--ease), color var(--t-fast) var(--ease);
}
.social-row a:hover { color: var(--brand); }
.social-row a:hover svg { transform: translateY(-4px) rotate(-6deg) scale(1.14); }
.social-row a:active svg { transform: translateY(-1px) scale(1.04); }

/* Entrance: the marks arrive one after another rather than all at once. */
.js .social-row a { opacity: 0; transform: translateY(10px); }
.js .social-row.in a {
  opacity: 1; transform: none;
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}
.js .social-row.in a:nth-child(1) { transition-delay: .04s; }
.js .social-row.in a:nth-child(2) { transition-delay: .12s; }
.js .social-row.in a:nth-child(3) { transition-delay: .20s; }
.js .social-row.in a:nth-child(4) { transition-delay: .28s; }

@media (prefers-reduced-motion: reduce) {
  .js .social-row a { opacity: 1; transform: none; }
  .social-row a:hover svg { transform: none; }
}

/* ---------- botanicals ----------
   Leaf sprigs and berry clusters lifted from the flyer. Decorative only:
   aria-hidden, never load-bearing, and sitting behind content at low opacity
   so they read as texture rather than illustration. */

.botanical {
  position: absolute;
  pointer-events: none;
  z-index: 0;
  opacity: .14;
  color: var(--brand);
}
.botanical svg { display: block; width: 100%; height: auto; }
.botanical.on-dark { opacity: .2; color: #fff; }
.botanical.accent { color: var(--accent); }

.bot-tl { top: -18px; left: -30px; width: clamp(110px, 15vw, 210px); transform: rotate(-8deg); }
.bot-br { bottom: -26px; right: -28px; width: clamp(120px, 17vw, 240px); transform: rotate(6deg); }
.bot-tr { top: -14px; right: -20px; width: clamp(90px, 12vw, 170px); transform: scaleX(-1) rotate(-10deg); }

@media (max-width: 700px) { .botanical { opacity: .09; } }

/* Sections holding one need to contain it and keep content above it. */
.has-botanical { position: relative; overflow: hidden; }
.has-botanical > .wrap { position: relative; z-index: 1; }

/* ---------- programme strip ----------
   The five tracks from the flyer, stated plainly under the hero so the offer
   is legible before anyone scrolls. */

.tracks {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 0;
  padding: 22px 0;
  background: var(--bg-soft);
}
.tracks span {
  display: inline-flex;
  align-items: center;
  padding: 0 clamp(12px, 2.4vw, 26px);
  font-family: var(--font-display);
  font-size: clamp(.9rem, 2vw, 1.15rem);
  font-weight: 600;
  color: var(--brand);
  white-space: nowrap;
}
/* Separator dots between tracks, none before the first on each line. */
.tracks span + span { border-left: 1px solid var(--hairline); }
@media (max-width: 700px) {
  .tracks span + span { border-left: 0; }
  .tracks span::after { content: '·'; margin-left: clamp(12px, 2.4vw, 26px); color: var(--accent); }
  .tracks span:last-child::after { content: none; }
}

/* Same idea as .tracks (a plain row under the hero) but for real jump
   links rather than static tags — a page long enough to have distinct
   sections (Work Abroad: offer / current opportunities / talent pool)
   gets one row of anchors so a visitor doesn't have to scroll blind. */
.page-subnav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px clamp(16px, 3vw, 30px);
  padding: 16px 0;
  background: var(--bg-soft);
}
.page-subnav a {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(.88rem, 1.8vw, 1rem);
  color: var(--brand);
  text-decoration: none;
  padding: 2px 1px;
  border-bottom: 2px solid transparent;
  transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.page-subnav a:hover { color: var(--accent); border-color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .page-subnav a { transition: none; }
}

/* ---------- journey ----------
   How it works, as a path that lights from the first step to the last as the
   reader scrolls. The connector is two stacked rules: a dim track, and a fill
   that grows when the step comes into view. */

.journey { list-style: none; padding: 0; margin: 36px 0 0; }

.journey li {
  position: relative;
  display: flex;
  gap: 20px;
  padding-bottom: 38px;
}
.journey li:last-child { padding-bottom: 0; }

/* the dim track */
.journey li::before {
  content: '';
  position: absolute; left: 17px; top: 40px; bottom: 0;
  width: 2px; background: var(--line);
}
/* the lit fill */
.journey li::after {
  content: '';
  position: absolute; left: 17px; top: 40px;
  width: 2px; height: 0;
  background: linear-gradient(var(--brand), var(--accent));
  transition: height .9s var(--ease) .15s;
}
.journey li.in::after { height: calc(100% - 40px); }
.journey li:last-child::before,
.journey li:last-child::after { display: none; }

.journey-node {
  flex: 0 0 36px;
  width: 36px; height: 36px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface);
  box-shadow: var(--shadow-well);
  color: var(--muted);
  font-weight: 700; font-size: .92rem;
  position: relative; z-index: 1;
  transition: background var(--t-med) var(--ease), color var(--t-med) var(--ease),
              box-shadow var(--t-med) var(--ease), transform var(--t-med) var(--ease);
}
.journey li.in .journey-node {
  background: var(--brand);
  color: var(--on-brand);
  transform: scale(1.06);
  box-shadow: 0 0 0 7px color-mix(in srgb, var(--brand) 13%, transparent);
}
.journey strong { display: block; margin-bottom: 2px; }
.journey span.body { color: var(--muted); font-size: .96rem; }

@media (prefers-reduced-motion: reduce) {
  .journey li::after { transition: none; }
}

/* ---------- furl ----------
   A collapsible panel. Built on <details> so it opens without JavaScript and
   announces its state to screen readers for free. Used for the contact form,
   which most visitors are not looking for and should not have to scroll past. */

.furl {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.furl > summary {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 20px 24px;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2.6vw, 1.35rem);
  font-weight: 600;
  transition: background var(--t-fast) var(--ease);
}
.furl > summary::-webkit-details-marker { display: none; }
.furl > summary:hover { background: color-mix(in srgb, var(--brand) 5%, var(--surface)); }

.furl > summary .furl-sub {
  display: block;
  font-family: var(--font-text);
  font-size: .87rem;
  font-weight: 400;
  color: var(--muted);
  margin-top: 3px;
}

/* Chevron, rotating on open. */
.furl > summary::after {
  content: '';
  margin-left: auto;
  flex: 0 0 auto;
  width: 10px; height: 10px;
  border-right: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--t-med) var(--ease);
}
.furl[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }

.furl-body { padding: 0 24px 24px; animation: furl-open .3s var(--ease); }

@keyframes furl-open {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- step form ----------
   One question at a time. The hero above stays put; only this card changes,
   so the page never jumps and the visitor keeps their bearings. */

.step-form { max-width: 620px; margin: 0 auto; }

.step-bar {
  height: 4px; border-radius: 999px; background: var(--line);
  overflow: hidden; margin-bottom: 10px;
}
.step-bar span {
  display: block; height: 100%; width: 0;
  background: var(--accent); border-radius: 999px;
  transition: width var(--t-med) var(--ease);
}
.step-count {
  font-size: .78rem; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 26px;
}

.q-card {
  background: var(--surface);
  border: 0;
  border-radius: var(--radius);
  padding: clamp(22px, 4vw, 36px);
  box-shadow: var(--shadow-lift);
}

/* Steps are stacked in the markup and revealed one at a time, so no content
   is lost if scripting fails — every field is still in the document. */
.step { display: none; border: 0; padding: 0; margin: 0; background: none; }
.step.current { display: block; animation: step-in .34s var(--ease); }

@keyframes step-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

.q-label {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 2.9vw, 1.6rem);
  font-weight: 600; line-height: 1.3;
  margin: 0 0 6px;
}
.q-hint { color: var(--muted); font-size: .93rem; margin: 0 0 20px; }

/* Roomier controls than the standard form: one question deserves the space. */
.step input[type="text"], .step input[type="email"], .step input[type="tel"], .step select {
  font-size: 1.08rem; padding: 15px 16px;
}

.step-nav { display: flex; gap: 12px; align-items: center; margin-top: 26px; }
.step-nav .btn { min-width: 130px; }
.step-back {
  background: none; border: 0; padding: 10px 4px; cursor: pointer;
  font: inherit; font-weight: 600; color: var(--muted);
}
.step-back:hover { color: var(--brand); }
.step-enter-hint { margin-left: auto; font-size: .8rem; color: var(--muted); }
@media (max-width: 560px) { .step-enter-hint { display: none; } }

/* Choice list — used for country and contact method, where tapping the answer
   is faster than opening a select. */
.choices { display: grid; gap: 10px; }
.choice {
  display: flex; align-items: center; gap: 12px;
  padding: 15px 16px; border: 0; border-radius: var(--radius-s);
  cursor: pointer; background: var(--surface);
  box-shadow: var(--shadow-well);
  transition: box-shadow var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.choice:hover { box-shadow: var(--shadow-well), inset 0 0 0 1.5px color-mix(in srgb, var(--brand) 45%, transparent); }
.choice input { width: auto; margin: 0; accent-color: var(--brand); flex: 0 0 auto; }
.choice.selected { background: color-mix(in srgb, var(--brand) 9%, var(--surface));
  box-shadow: inset 0 0 0 1.5px var(--brand); }
.choice-text strong { display: block; font-size: 1rem; }
.choice-text span { font-size: .87rem; color: var(--muted); }

/* Review step */
.review { display: grid; gap: 2px; margin-bottom: 22px; }
.review-row {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 11px 0; border-bottom: 1px solid var(--hairline); font-size: .95rem;
}
.review-row:last-child { border-bottom: 0; }
.review-row dt { color: var(--muted); margin: 0; }
.review-row dd { margin: 0; font-weight: 600; text-align: right; }
.review-edit {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: .82rem; font-weight: 600; color: var(--brand);
  text-decoration: none; margin-left: 10px;
}

/* ---------- news ---------- */

.news-item {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  margin-bottom: 26px;
  transition: box-shadow var(--t-med) var(--ease), transform var(--t-med) var(--ease);
}
.news-item:hover { box-shadow: var(--shadow-lift); transform: translateY(-3px); }

.news-image { aspect-ratio: 16 / 9; background: var(--bg-soft); }
.news-image img { width: 100%; height: 100%; object-fit: cover; display: block; }

.news-body { padding: clamp(20px, 3.4vw, 30px); }
.news-body h2 { font-size: clamp(1.2rem, 2.6vw, 1.6rem); margin-bottom: .35em; }
.news-summary { color: var(--muted); font-size: 1.02rem; }

.news-meta {
  display: flex; align-items: center; gap: 10px;
  font-size: .78rem; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 10px;
}
.news-flag {
  padding: 3px 10px; border-radius: 999px; letter-spacing: .06em;
  background: color-mix(in srgb, var(--accent) 15%, var(--surface)); color: var(--accent);
}
.news-flag.instagram {
  background: color-mix(in srgb, var(--brand) 14%, var(--surface)); color: var(--brand);
}

.follow-cta {
  background: var(--bg-soft);
  border-radius: var(--radius);
  padding: clamp(22px, 4vw, 34px);
  box-shadow: var(--shadow-well);
}
.follow-cta h2 { margin-bottom: .2em; }

/* ---------- locations ----------
   Grouped by country, cities beneath. One country today; the shape is what
   matters, so adding the second is markup rather than a redesign. */

.country-group + .country-group { margin-top: 48px; }

.country-head {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding-bottom: 12px; margin-bottom: 24px;
  border-bottom: 1px solid var(--hairline);
}
.country-head h2 { margin: 0; }
.country-flag {
  font-size: .72rem; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--accent);
}

/* ---------- locations ---------- */

.loc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 24px;
  margin-top: 34px;
}

.loc-card {
  background: var(--surface);
  border: 0;
  border-radius: var(--radius);
  padding: 28px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: border-color var(--t-med) var(--ease), box-shadow var(--t-med) var(--ease);
}
.loc-card:hover { box-shadow: var(--shadow-lift); }

.loc-country {
  font-size: .72rem; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--accent); margin: 0;
}
.loc-city { font-family: var(--font-display); font-size: 1.45rem; font-weight: 500; margin: 0 0 12px; }

.loc-address { align-items: flex-start; font-size: .97rem; line-height: 1.55; margin-bottom: 16px; }
.loc-address svg { margin-top: 3px; color: var(--brand); }

.loc-actions { display: grid; gap: 10px; margin-bottom: 20px; font-size: .95rem; }
.loc-actions svg { color: var(--brand); }

.loc-note { color: var(--muted); font-size: .95rem; margin-bottom: 14px; }

.loc-social-label {
  font-size: .78rem; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin: 4px 0 10px;
}

/* Push the button to the bottom so cards of different heights line up. */
.loc-cta { margin-top: auto; align-self: flex-start; }

/* ---------- section icon ----------
   A brand-coloured line icon in front of a heading (Kids category
   sections) — standing in for a colourful emoji, which reads as
   inconsistent with the rest of the site's monochrome iconography. */

.section-icon {
  width: 1.15em;
  height: 1.15em;
  margin-right: 0.35em;
  vertical-align: -0.15em;
  color: var(--brand);
}

/* ---------- numbered stages ----------
   Used on study-abroad, where the order is the argument: each stage is only
   worth buying if the one before it came back positive. */

.stages { display: grid; gap: 18px; }

.stage {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 18px;
  align-items: start;
  padding: clamp(20px, 3vw, 26px);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}
.stage h3 { margin: 0; }
.stage p { margin: 8px 0 0; }

.stage-n {
  display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--brand); color: #fff;
  font-family: var(--font-display); font-size: 1.15rem; font-weight: 600;
  line-height: 1;
}

/* Blank until the catalogue answers, so a failed fetch shows nothing rather
   than a stale number. See study-abroad.js. */
.stage-price {
  font-weight: 700; color: var(--accent);
  font-size: 1.05rem; min-height: 1.2em;
}

@media (max-width: 520px) {
  .stage { grid-template-columns: 1fr; gap: 12px; }
}

/* Two actions side by side, and never touching once they wrap. */
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
.btn-row .btn { margin: 0; }
@media (max-width: 420px) {
  .btn-row { flex-direction: column; align-items: stretch; }
  .btn-row .btn { text-align: center; }
}

.stage-go { margin-top: 14px; }
.stage-go a {
  font-weight: 600; color: var(--accent); text-decoration: none; cursor: pointer;
  display: inline-block; transition: transform var(--t-fast) var(--ease);
}
.stage-go a:hover { transform: translateX(3px); }

/* The enquiry box. A <dialog> so Escape and the focus trap come free. */
.ask-dialog {
  width: min(560px, calc(100vw - 2 * var(--gutter)));
  padding: clamp(20px, 4vw, 30px);
  border: 0; border-radius: var(--radius);
  background: var(--surface); color: var(--ink);
  box-shadow: var(--shadow-lift);
}
.ask-dialog::backdrop { background: rgba(10,14,15,.62); }
.ask-head { display: flex; align-items: start; justify-content: space-between; gap: 14px; }
.ask-head h2 { margin: 0 0 6px; font-size: 1.35rem; }
.ask-close {
  background: none; border: 0; cursor: pointer; line-height: 1;
  font-size: 1.7rem; color: var(--muted); padding: 0 4px;
  transition: color var(--t-fast) var(--ease);
}
.ask-close:hover { color: var(--accent); }

.done-panel { text-align: center; padding: clamp(20px, 4vw, 34px) 0; }
.done-panel h2 { margin: 0 0 10px; }
.done-panel .btn-row { justify-content: center; }
.done-id {
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: clamp(1.7rem, 6vw, 2.4rem); font-weight: 700;
  letter-spacing: .06em; color: var(--brand);
  margin: 18px 0; word-break: break-all;
}

/* A list that reads as prose rather than a bulleted inventory. */
.plain-list { list-style: none; padding: 0; margin: 20px 0 0; display: grid; gap: 14px; }
.plain-list li { padding-left: 20px; position: relative; }
.plain-list li::before {
  content: ''; position: absolute; left: 0; top: .62em;
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
}

/* ---------- footer ----------
   Three columns over a copyright strip. The strip is pure black, one shade
   below the midnight above it, so the two read as separate bands with no
   border drawn between them. It is padded to the height of its one line and
   no more, which is the whole point of it. */

footer {
  background: var(--c-midnight);
  color: rgba(255,255,255,.68);
  font-size: .9rem;
  margin-top: 56px;
}

.foot-grid {
  display: grid;
  grid-template-columns: 1.7fr 1fr 1fr;
  gap: clamp(30px, 5vw, 64px);
  /* Vertical only. A shorthand here would override the side padding .wrap
     already sets on this same element, and the footer would run to the edge. */
  padding-top: clamp(38px, 5vw, 58px);
  padding-bottom: clamp(38px, 5vw, 58px);
}

.foot-brand {
  display: inline-flex; align-items: center; gap: 12px;
  margin-bottom: 18px; text-decoration: none;
}
/* Bleached to flat white. The mark is drawn for a cream page and goes muddy
   against midnight, and unlike the header this bar is dark in both themes. */
.foot-brand img { width: 46px; height: auto; filter: brightness(0) invert(1); }
.foot-brand span {
  font-family: var(--font-display); font-size: 1.2rem; font-weight: 600;
  letter-spacing: -.01em; color: #fff;
}
.foot-about p { margin: 0; max-width: 44ch; line-height: 1.7; }

.foot-social { display: flex; gap: 12px; margin-top: 22px; }
.foot-social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  color: rgba(255,255,255,.75);
  background: rgba(255,255,255,.07);
  transition: transform .3s var(--ease),
              background var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
}
.foot-social svg { width: 18px; height: 18px; }
.foot-social a:hover {
  color: #fff; background: var(--c-rust); transform: translateY(-3px);
}

.foot-col { display: flex; flex-direction: column; gap: 11px; }
.foot-col h2 {
  margin: 0 0 15px;
  font-size: .76rem; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase;
  color: rgba(255,255,255,.45);
}
.foot-col a {
  width: fit-content;
  color: rgba(255,255,255,.72); text-decoration: none;
  transition: color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.foot-col a:hover { color: #fff; transform: translateX(3px); }

.foot-base {
  background: #000;
  padding: 11px 0;
  font-size: .82rem;
  color: rgba(255,255,255,.5);
}
.foot-base p { margin: 0; text-align: center; }

/* The summary runs full width and the two link columns pair up beneath it,
   which keeps the footer short instead of stacking three tall blocks. */
@media (max-width: 820px) {
  .foot-grid { grid-template-columns: 1fr 1fr; gap: 34px 24px; }
  .foot-about { grid-column: 1 / -1; }
}
@media (max-width: 440px) {
  .foot-grid { grid-template-columns: 1fr; gap: 30px; }
}
@media (prefers-reduced-motion: reduce) {
  .foot-social a:hover, .foot-col a:hover { transform: none; }
}

/* ---------- entrance animation ----------
   Elements marked .reveal fade up once, driven by a small observer in app.js.
   Anyone who has asked for less motion simply gets the finished state. */

/* Scoped to .js — set by the inline head script — so a page whose JavaScript
   fails to load shows its content rather than a blank screen. Whole sections
   carry this class on some pages, so the failure mode matters. */
.js .reveal { opacity: 0; transform: translateY(18px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
.js .reveal.in { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: .08s; }
.reveal-d2 { transition-delay: .16s; }
.reveal-d3 { transition-delay: .24s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  .reveal { opacity: 1; transform: none; }
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ---------- dashboard shell ----------
   do-now.md: one consistent nav shell for the whole admin dashboard —
   sidebar + header on the legal-chrome dashboard.html page (no marketing
   header/footer here, see tools/shared.mjs's legalTop()). Every .dash-card
   this page already had is untouched; this only adds the header, the
   sidebar, and section show/hide driven by dashboard-shell.js. */

.dash-shell { display: flex; flex-direction: column; min-height: 100vh; }

.dash-shell-header {
  display: flex; align-items: center; gap: 14px;
  padding: 10px clamp(14px, 3vw, 24px);
  background: var(--surface);
  border-bottom: 1px solid var(--hairline);
  position: sticky; top: 0; z-index: 40;
}

.dash-hamburger {
  display: none;
  align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0; flex: 0 0 auto;
  background: none; border: 0; border-radius: var(--radius-s);
  color: var(--ink); cursor: pointer;
}
.dash-hamburger:hover { background: var(--bg-soft); }
.dash-hamburger svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; }

.dash-brand {
  display: flex; align-items: center; gap: 8px;
  color: var(--ink) !important; text-decoration: none; font-weight: 700;
  flex: 0 0 auto;
}
.dash-brand img { width: 26px; height: 26px; border-radius: 6px; }

.dash-shell-title {
  flex: 1; min-width: 0;
  font-family: var(--font-display); font-size: 1.15rem; font-weight: 600;
  margin: 0; display: flex; align-items: center; flex-wrap: wrap;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.dash-shell-actions { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }

.dash-icon-btn {
  position: relative;
  display: grid; place-items: center;
  width: 36px; height: 36px; padding: 0;
  background: none; border: 0; border-radius: 50%;
  color: var(--ink); cursor: pointer;
}
.dash-icon-btn:hover { background: var(--bg-soft); }
.dash-icon-btn svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.8; }

.dash-badge {
  position: absolute; top: 2px; right: 2px;
  min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: 999px;
  background: var(--accent); color: var(--on-accent);
  font-size: .62rem; font-weight: 700; line-height: 15px; text-align: center;
}

.dash-notif-wrap { position: relative; }
.dash-notif-panel {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: min(360px, 88vw); max-height: 70vh; overflow-y: auto;
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow-lift); z-index: 50;
}
.dash-notif-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--hairline);
}
.dash-notif-row {
  display: flex; align-items: flex-start; gap: 10px; width: 100%;
  padding: 12px 16px; background: none; border: 0; border-top: 1px solid var(--hairline);
  text-align: left; cursor: pointer; color: inherit; font: inherit;
}
.dash-notif-row:first-of-type { border-top: 0; }
.dash-notif-row:hover { background: var(--bg-soft); }
.dash-notif-dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; margin-top: 6px;
  background: transparent;
}
.dash-notif-row.unread .dash-notif-dot { background: var(--brand); }
.dash-notif-row.unread strong { color: var(--brand); }
.dash-notif-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dash-notif-text { color: var(--muted); font-size: .85rem; }
.dash-notif-when { color: var(--muted); font-size: .76rem; }

.dash-shell-body { display: flex; flex: 1; min-height: 0; }

.dash-scrim { position: fixed; inset: 0; background: rgba(10, 14, 15, .5); z-index: 45; }

.dash-sidebar {
  flex: 0 0 232px; width: 232px;
  display: flex; flex-direction: column; gap: 2px;
  padding: 16px 12px;
  background: var(--surface); border-right: 1px solid var(--hairline);
  position: sticky; top: 57px; align-self: flex-start;
  max-height: calc(100vh - 57px); overflow-y: auto;
}

.dash-nav-item {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; border-radius: var(--radius-s);
  background: none; border: 0; color: var(--ink);
  font: inherit; font-size: .93rem; text-align: left; cursor: pointer;
}
/* .dash-nav-item's own display:flex has the same specificity as the
   browser's default [hidden]{display:none}, and comes later in the
   cascade, so it silently won it: dashboard-shell.js's dash:pruned
   listener sets navBtn.hidden = true for sections a login has nothing
   in, but the button stayed fully visible and clickable regardless —
   same shape of bug as the step-form "current" class contract. */
.dash-nav-item[hidden] { display: none; }
.dash-nav-item:hover { background: var(--bg-soft); }
.dash-nav-item.active { background: color-mix(in srgb, var(--brand) 13%, transparent); color: var(--brand); font-weight: 600; }
.dash-nav-item svg { flex: 0 0 auto; width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; }

.dash-main { flex: 1; min-width: 0; padding: 26px 0 60px; }

.dash-kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px; margin-bottom: 4px;
}
.dash-kpi {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 16px 18px; display: flex; flex-direction: column; gap: 2px;
}
.dash-kpi-value { font-size: 1.7rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.dash-kpi-label { color: var(--muted); font-size: .82rem; }

.dash-section { display: none; }
.dash-section.active { display: grid; }

@media (max-width: 900px) {
  .dash-hamburger { display: flex; }
  .dash-brand span { display: none; }

  .dash-sidebar {
    position: fixed; top: 57px; left: 0; bottom: 0; z-index: 46;
    max-height: none;
    transform: translateX(-100%);
    transition: transform var(--t-med) var(--ease);
    box-shadow: var(--shadow-lift);
  }
  .dash-shell.dash-drawer-open .dash-sidebar { transform: translateX(0); }
  .dash-shell:not(.dash-drawer-open) .dash-scrim { display: none; }
}

@media (min-width: 901px) {
  .dash-scrim { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .dash-sidebar { transition: none; }
}
