/* HDB Connect
   One board for Hubballi, Dharwad and Belagavi.

   Palette pulled straight from the mark: three interlocking rings in azure
   #0d8fd0, teal #1a9a95 and leaf #6f9f43 — one ring per city. Azure carries the
   interface because it is the ring the eye lands on first; teal and leaf are
   kept for accents so the other two cities are never decoration-only.

   Shape language is a rounded RECTANGLE, not a pill: three names in the brand
   means more long labels than a one-word city has, and a 10px radius holds them
   without the ends ballooning. Chips stay pill-shaped — they are the one place
   a capsule reads as "filter" rather than "button". */

/* ---------------------------------------------------------------- fonts --
   Quicksand (display) and Nunito (text), both OFL-1.1, self-hosted from
   /assets/fonts so the page makes no third-party request. Licences sit
   alongside the files. Both are variable fonts: one file per subset covers
   the whole weight range, so there is nothing else to download for bold.   */

@font-face {
  font-family: "Quicksand";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/quicksand-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Quicksand";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/quicksand-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Nunito";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/assets/fonts/nunito-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Nunito";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/assets/fonts/nunito-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* Azure, deepened from the mark's #0d8fd0 so body-size text on paper clears
     4.5:1. The bright original survives as --azure, for fills only. */
  --brand:      #0c6f9e;
  --brand-700:  #08536f;
  --brand-300:  #7ab6d4;
  --brand-100:  #d6e9f4;
  --brand-050:  #eef7fb;
  --azure:      #0d8fd0;

  /* The other two rings. Each one is a real accent with a job, not a spare
     colour: teal marks confirmed things, leaf marks money and pay. */
  --teal:       #17948f;
  --teal-soft:  #e0f3f1;
  --leaf:       #5d8a37;
  --leaf-soft:  #eaf3df;

  --ink:         #10242e;
  --ink-soft:    #4c626d;
  --ink-faint:   #83949d;

  /* Cool paper, not warm. The mark is a cold palette and a cream ground made
     the azure look muddy against it. */
  --paper:       #f6fafc;
  --surface:     #ffffff;
  --line:        #e0e9ee;
  --line-soft:   #eef4f7;

  --heart:       #d94f5c;
  /* mint is the "confirmed / good" colour throughout; here it IS the teal ring,
     so the two names point at one value on purpose. */
  --mint:        #17948f;
  --mint-soft:   #e0f3f1;
  --amber:       #bd7f24;
  --amber-soft:  #fcf2e0;
  /* Unclaimed: a cool slate rather than sand. It has to read as "incomplete",
     never as a warning, and warm sand next to a cold palette read as a caution. */
  --sand:        #c7d5dc;
  --sand-soft:   #eef3f6;
  --sand-ink:    #647c88;

  --r-sm:  6px;
  --r-md:  10px;
  --r-lg:  14px;
  --r-xl:  20px;
  --r-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(16, 36, 46, .06);
  --shadow-md: 0 4px 16px rgba(16, 36, 46, .08);
  --shadow-lg: 0 14px 40px rgba(12, 111, 158, .14);

  /* The three rings as a line, used on the header rule, card tops and the
     footer. It is the one graphic device that says "three cities" without
     spelling it out. */
  --rings: linear-gradient(90deg, var(--azure), var(--teal) 52%, var(--leaf));

  /* Self-hosted rounded type. The system faces stay on as fallbacks for the
     moment before the woff2 lands, and for anything outside latin/latin-ext
     (a listing written in Kannada or Devanagari falls through to the OS). */
  --font: "Nunito", ui-rounded, "SF Pro Rounded", "Hiragino Maru Gothic ProN",
          "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-display: "Quicksand", "Nunito", ui-rounded, "SF Pro Rounded",
          "Segoe UI Variable Display", system-ui, -apple-system, sans-serif;
}

* { box-sizing: border-box; }

/* The browser's own [hidden] rule is display:none, which any author rule that
   sets display — .btn is inline-flex, .edit-panel is grid — silently beats.
   Without this, `el.hidden = true` does nothing to those elements. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }

/* Keep anchored sections clear of the sticky header. */
section[id] { scroll-margin-top: 88px; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 700; letter-spacing: -.02em; line-height: 1.15; margin: 0;
}

a { color: var(--brand); }

.wrap { width: min(1140px, 100% - 40px); margin-inline: auto; }

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

.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(246, 250, 252, .9);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
/* The three rings, drawn as a hairline under the header. It is the site's
   signature and costs no vertical space. */
.site-header::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: var(--rings);
}

/* Five boards do not fit on one line beside the brand at phone width: measured,
   they need 372px against the 252px a 320px screen leaves. So the row WRAPS,
   and the boards drop to a full-width second row below 720px. Nothing is
   hidden and nothing scrolls sideways — see the media query at the foot of this
   file, and invariant 13. */
.site-header .wrap {
  display: flex; align-items: center; gap: 16px;
  min-height: 72px; flex-wrap: wrap;
}

.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; color: inherit; }
.brand img { width: 40px; height: 40px; display: block; }

.brand-text { display: flex; flex-direction: column; line-height: 1; }
.brand-name { font-family: var(--font-display); font-size: 20px; font-weight: 700; letter-spacing: -.03em; color: var(--brand); }
/* The three cities, spelled out. "HDB" means nothing to someone arriving cold,
   so the expansion travels with the wordmark everywhere it appears. */
.brand-tag  { font-size: 11.5px; font-weight: 700; color: var(--ink-faint); letter-spacing: .04em; margin-top: 3px; }
.brand-tag .dot { color: var(--brand-300); margin: 0 .28em; }

.header-spacer { flex: 1; }

/* The boards. Their own element so they can move to a row of their own. */
.board-nav { display: flex; align-items: center; gap: 4px; }
.board-link {
  color: var(--ink-soft); text-decoration: none; font-weight: 600;
  font-size: 15px; padding: 9px 13px; border-radius: var(--r-sm);
  white-space: nowrap;
  transition: background .14s ease, color .14s ease;
}
.board-link:hover { background: var(--brand-050); color: var(--brand); }
/* The board you are on, marked with its own underline rather than a fill: a
   filled pill here would compete with the city filter's filled segments a few
   hundred pixels below it, and they mean different things. */
.board-link.on { color: var(--brand); background: var(--brand-050); }

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

.btn {
  font: inherit; font-family: var(--font-display);
  font-weight: 700; font-size: 15px;
  border: 0; cursor: pointer;
  padding: 11px 20px; border-radius: var(--r-md);
  background: var(--brand); color: #fff;
  text-decoration: none; display: inline-flex; align-items: center; gap: 8px;
  transition: transform .15s ease, background .15s ease, box-shadow .15s ease;
  box-shadow: var(--shadow-sm);
}
.btn:hover { background: var(--brand-700); transform: translateY(-1px); box-shadow: var(--shadow-md); }
.btn:active { transform: translateY(0); }
.btn:disabled { opacity: .55; cursor: not-allowed; transform: none; }

.btn.ghost { background: var(--surface); color: var(--brand); border: 1.5px solid var(--brand-100); }
.btn.ghost:hover { background: var(--brand-050); border-color: var(--brand-300); }

.btn.small { padding: 7px 13px; font-size: 13.5px; border-radius: var(--r-sm); }

/* ------------------------------------------------------------------ hero -- */
/*
 * A two-column hero, left-aligned. The reference this grew from centred
 * everything, which works for one short city name; "Hubballi · Dharwad ·
 * Belagavi" plus a rotating city word is a lot of text to keep balanced around
 * an axis, and centred type re-centres on every word swap. Ranged left it
 * simply sits still.
 *
 * The right column is the mark, large and quiet, with the live counts sitting
 * on it — the numbers are the proof the wall is real, so they get a surface of
 * their own rather than a row of figures under a paragraph.
 */

.hero { padding: 68px 0 40px; position: relative; overflow: hidden; }

.hero::before {
  content: ""; position: absolute; inset: -40% auto auto -10%; width: 780px; height: 780px;
  background: radial-gradient(circle at 30% 35%, var(--brand-050), transparent 62%);
  pointer-events: none;
}

.hero .wrap {
  position: relative;
  display: grid; align-items: center; gap: clamp(28px, 5vw, 64px);
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
}

/* ---- left column ---- */

/* The jobs and events board label — "Jobs in Dharwad", "Happening in Hubballi".
   Named for the boards rather than for its copy: it used to read "Made with ❤️"
   and was called `.made-eyebrow`, which stayed accurate for exactly as long as
   that sentence did.

   A label, not a caption. One hairline, on the right only — a ranged-left
   eyebrow needs a rule that runs away from the text, not a pair bracketing it.
   It is a real element rather than ::after so it can shrink on a narrow screen
   instead of forcing the line wider than the viewport.

   Used by the jobs and events boards ("Jobs in Dharwad", "Happening in …").
   The wall's hero has none: its wordmark, the city line under it and the
   segmented filter already say where you are three times over. */
.board-eyebrow {
  display: flex; align-items: center;
  gap: clamp(9px, 2.2vw, 15px);
  margin: 0 0 14px;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(11.5px, 2.2vw, 14px);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-faint);
}
.be-line {
  height: 2px; border-radius: 2px; background: var(--rings);
  /* Shrinks before the text does, so the words never break up. */
  flex: 0 1 clamp(20px, 8vw, 72px);
  min-width: 14px;
}
/* Letter-spacing leaves a trailing gap after the last glyph, which would sit
   the rule further from the text than it looks. Pull it back. */
.be-text { margin-right: -.18em; white-space: nowrap; }

.wordmark {
  font-family: var(--font-display);
  font-size: clamp(44px, 7.4vw, 76px);
  font-weight: 700; letter-spacing: -.045em; color: var(--brand);
  line-height: 1.02; margin: 0;
}
/* "Connect" in teal — the second ring, so the wordmark itself carries more than
   one city's colour. */
.wordmark .wm-b { color: var(--teal); }

/* The three cities under the wordmark, at a size you can actually read. This is
   the line that explains what HDB stands for, so it is never decoration. */
.hero-cities {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 6px 10px; margin: 12px 0 0;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(15px, 2.4vw, 19px); letter-spacing: -.01em;
  color: var(--ink-soft);
}
.hero-cities .hc-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.hero-cities .hc:nth-of-type(1) .hc-dot { background: var(--azure); }
.hero-cities .hc:nth-of-type(2) .hc-dot { background: var(--teal); }
.hero-cities .hc:nth-of-type(3) .hc-dot { background: var(--leaf); }
.hero-cities .hc { display: inline-flex; align-items: center; gap: 7px; }

.hero-sub {
  max-width: 52ch; margin: 20px 0 0;
  font-size: 17.5px; color: var(--ink-soft); line-height: 1.55;
}

.hero-actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 28px; }

/* ---- right column: the mark, with the counts sitting on it ---- */

.hero-panel {
  position: relative; display: grid; place-items: center;
  padding: 8px;
}

/* Capped at the source's own resolution. The mark is a 290px PNG, so anything
   above that is the browser inventing pixels — and measured, an offline upscale
   to 600px came out SOFTER than the original (45.0% edge pixels against 40.8%)
   as well as 3x the bytes. Raise this only when a larger original exists. */
.hero-stamp {
  width: min(290px, 100%); height: auto; display: block;
  animation: settle .7s cubic-bezier(.2,.8,.3,1) both;
}
@keyframes settle {
  from { opacity: 0; transform: translateY(-10px) rotate(-8deg) scale(.9); }
  to   { opacity: 1; transform: none; }
}

.hero-stats {
  position: absolute; left: 50%; bottom: -6px; transform: translateX(-50%);
  display: flex; gap: 4px; align-items: stretch;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-md);
  padding: 12px 6px;
}
.hero-stats > div { padding: 0 16px; text-align: center; min-width: 78px; }
.hero-stats > div + div { border-left: 1px solid var(--line-soft); }
.stat-n { font-family: var(--font-display); font-size: 24px; font-weight: 700; color: var(--brand); letter-spacing: -.03em; line-height: 1.15; }
.stat-l { font-size: 11px; color: var(--ink-faint); font-weight: 700; text-transform: uppercase; letter-spacing: .07em; }

/* Below the split, the mark is a header ornament rather than a column: it goes
   above the text at a fraction of the size, and the counts return to a plain
   row because a floating panel over a 120px mark has nothing to float on. */
@media (max-width: 900px) {
  .hero .wrap { grid-template-columns: 1fr; gap: 0; }
  .hero-panel { order: -1; justify-items: start; place-items: start; padding: 0 0 18px; }
  .hero-stamp { width: 96px; }
  .hero-stats {
    position: static; transform: none; margin-top: 32px;
    box-shadow: none; padding: 14px 4px;
  }
  .hero-stats > div { padding: 0 18px; text-align: left; }
}

/* --------------------------------------------------------------- filters -- */
/*
 * Which city is the first question on a three-city board, so it gets a control
 * of its own above the search row rather than another chip in the same tray as
 * twelve categories. Segmented, not a select: three options plus "All" is small
 * enough to show whole, and seeing the other two cities named is half the point
 * of the site.
 *
 * Each segment carries its city's ring colour when active, so the mark in the
 * header and the filter you pressed agree with each other.
 */
.cities {
  display: flex; gap: 4px; flex-wrap: wrap;
  margin: 38px 0 0; padding: 5px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-sm);
  width: fit-content; max-width: 100%;
}
.city-seg {
  font: inherit; font-family: var(--font-display); font-weight: 700; font-size: 14.5px;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 16px; cursor: pointer; white-space: nowrap;
  border: 0; border-radius: var(--r-md);
  background: none; color: var(--ink-soft);
  transition: background .14s ease, color .14s ease;
}
.city-seg:hover { background: var(--brand-050); color: var(--brand); }
.city-seg:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.city-seg .cd { width: 9px; height: 9px; border-radius: 50%; flex: none; background: var(--sand); }
.city-seg[data-city="Hubballi"] .cd { background: var(--azure); }
.city-seg[data-city="Dharwad"]  .cd { background: var(--teal); }
.city-seg[data-city="Belagavi"] .cd { background: var(--leaf); }
/* "All" gets the whole mark rather than one ring. */
.city-seg[data-city=""] .cd { background: var(--rings); }

.city-seg[aria-pressed="true"] { background: var(--brand); color: #fff; }
.city-seg[aria-pressed="true"] .cd { box-shadow: 0 0 0 2px rgba(255,255,255,.5); }
.city-seg[aria-pressed="true"][data-city="Dharwad"]  { background: var(--teal); }
.city-seg[aria-pressed="true"][data-city="Belagavi"] { background: var(--leaf); }

.city-count { font-weight: 700; font-size: 12.5px; opacity: .65; font-variant-numeric: tabular-nums; }

@media (max-width: 560px) {
  .cities { width: 100%; }
  .city-seg { flex: 1 1 auto; justify-content: center; padding: 9px 10px; font-size: 13.5px; }
}

.toolbar {
  display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
  margin: 18px 0 22px;
}

.search {
  flex: 1 1 260px; min-width: 220px; position: relative;
}
.search input {
  width: 100%; font: inherit; font-size: 15px;
  padding: 12px 18px 12px 44px;
  border: 1.5px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink);
}
.search input:focus { outline: none; border-color: var(--brand-300); box-shadow: 0 0 0 4px var(--brand-050); }
.search svg { position: absolute; left: 16px; top: 50%; transform: translateY(-50%); color: var(--ink-faint); }

.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  font: inherit; font-family: var(--font-display); font-size: 14px; font-weight: 600; cursor: pointer;
  padding: 8px 15px; border-radius: var(--r-pill);
  border: 1.5px solid var(--line); background: var(--surface); color: var(--ink-soft);
  transition: all .14s ease; white-space: nowrap;
}
.chip:hover { border-color: var(--brand-300); color: var(--brand); }
.chip[aria-pressed="true"] { background: var(--brand); border-color: var(--brand); color: #fff; }

/* ----------------------------------------------------------------- cards -- */

/* Every board grid writes its column minimum as min(Npx, 100%), never a bare
   Npx. A 320px phone leaves 288px of content, and every one of these minimums
   is wider than that, so a bare value made every board scroll sideways on a
   small phone. It went unnoticed because it was measured against innerWidth,
   which the emulator over-reports; clientWidth shows it. A test pins this. */
.grid {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fill, minmax(min(310px, 100%), 1fr));
  margin-bottom: 56px;
}

/* A card is a rounded rectangle with a coloured cap: 3px of its city's ring
   across the top edge. It tells you which of the three cities a listing is from
   before you read a word of it, and it is the reason the board can stay one
   grid instead of three sections. */
.card {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 22px 22px 0;
  display: flex; flex-direction: column;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
/* One rule for all three boards. A job card and an event card carry the same
   cap as a listing card, because the colour code is only worth learning if it
   means the same thing everywhere. */
.card::before,
.job-card::before,
.event-card::before,
.inst-card::before,
.exp-card::before,
.cw-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--sand);
}
[data-city="Hubballi"]::before { background: var(--azure); }
[data-city="Dharwad"]::before  { background: var(--teal); }
[data-city="Belagavi"]::before { background: var(--leaf); }
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--brand-100); }

.card-top { display: flex; align-items: flex-start; gap: 13px; }

.card-emoji {
  width: 48px; height: 48px; flex: none;
  display: grid; place-items: center; font-size: 24px;
  background: var(--brand-050); border-radius: var(--r-md);
}

/* The city, on the card, in words. The cap stripe alone is a colour code only
   a returning visitor knows how to read. */
.card-city {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-display); font-size: 12.5px; font-weight: 700;
  color: var(--ink-faint); margin-top: 2px;
}
.card-city .cd { width: 8px; height: 8px; border-radius: 50%; background: var(--sand); }
.card[data-city="Hubballi"] .card-city .cd { background: var(--azure); }
.card[data-city="Dharwad"]  .card-city .cd { background: var(--teal); }
.card[data-city="Belagavi"] .card-city .cd { background: var(--leaf); }

.card-name { font-family: var(--font-display); font-size: 18.5px; font-weight: 700; letter-spacing: -.02em; }
.card-name a { color: inherit; text-decoration: none; }
.card-name a:hover { color: var(--brand); }

.card-tagline { color: var(--ink-soft); font-size: 15px; margin: 10px 0 0; }

.badges { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.badge {
  font-size: 11.5px; font-weight: 700; letter-spacing: .03em;
  padding: 3px 10px; border-radius: var(--r-pill);
  background: var(--brand-050); color: var(--brand);
}
.badge.verified { background: var(--mint-soft); color: var(--mint); }
.badge.curated  { background: var(--line-soft); color: var(--ink-faint); }
.badge.checking { background: var(--amber-soft); color: var(--amber); }
/* Unclaimed: a soft, neutral sand — deliberately NOT the amber of a moderation
   state and nowhere near a warning red. It reads as "incomplete", not "suspect". */
.badge.unclaimed { background: var(--sand-soft); color: var(--sand-ink); }

/* An unclaimed card is quieter than a claimed one, and its dashed edge reads as
   an outline waiting to be filled in. It must still look like a real listing —
   these are genuine Belagavi businesses that simply have not been claimed. */
.card.unclaimed { border-style: dashed; border-color: var(--sand); background: var(--surface); }
/* The cap is drawn inside the border box, so a dashed border would show through
   it. Keep the stripe solid — it identifies the city, not the claim state. */
.card.unclaimed::before { opacity: .55; }
.card.unclaimed:hover { border-style: solid; border-color: var(--brand-100); }

/* Used on listing pages (the "Edit this listing" link). Cards use .pill-act. */
.claim-cta {
  font: inherit; font-family: var(--font-display); font-size: 12.5px; font-weight: 700;
  cursor: pointer; border: 0; background: none; color: var(--brand);
  padding: 0; text-decoration: underline; text-underline-offset: 3px;
}
.claim-cta:hover { color: var(--brand-700); }
.people { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; color: var(--mint); }

.card-meta {
  display: flex; gap: 14px; flex-wrap: wrap;
  margin-top: 16px; font-size: 13px; color: var(--ink-faint); font-weight: 600;
}
.card-meta a { color: var(--brand); text-decoration: none; }
.card-meta a:hover { text-decoration: underline; }

/* The line that ties every listing back to the brand. */
.card-foot {
  margin-top: auto; padding: 12px 0 16px;
  border-top: 1px dashed var(--line);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
/* Reactions and the report flag are neighbours now — one positive, one not.
   Keep enough of a gap that nobody reaches for one and hits the other. */
.card-foot .reacts + .icon-btn { margin-left: 4px; }
.foot-spacer { flex: 1 1 auto; }

/* A text action sized to sit level with the reaction pill, so the row reads as
   one set of controls rather than three unrelated widgets. */
.pill-act {
  font: inherit; font-family: var(--font-display); font-weight: 700; font-size: 13px;
  padding: 5px 12px; cursor: pointer; white-space: nowrap;
  border: 1.5px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-soft);
  transition: border-color .14s ease, background .14s ease, color .14s ease;
}
.pill-act:hover { border-color: var(--brand-300); background: var(--brand-050); color: var(--brand); }
.pill-act:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.made-in {
  font-family: var(--font-display);
  font-size: 12.5px; font-weight: 700; color: var(--ink-faint);
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
}

.card-acts { display: flex; gap: 6px; align-items: center; }

/* ---------------------------------------------------------------- reactions -- */

.reacts { position: relative; display: flex; align-items: center; gap: 6px; }

.react-pill {
  font: inherit; font-family: var(--font-display); font-weight: 700; font-size: 13px;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px 5px 9px; cursor: pointer;
  border: 1.5px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-soft);
  transition: border-color .14s ease, background .14s ease;
}
.react-pill:hover { border-color: var(--brand-300); background: var(--brand-050); }
.react-pill.mine { border-color: var(--brand-100); background: var(--brand-050); color: var(--brand); }
/* Emoji carry their own side bearings, so the negative margin that makes
   avatar stacks look neat just makes these look broken. Space them instead. */
.react-pill .faces { display: inline-flex; gap: 3px; font-size: 14px; line-height: 1; }
.react-pill .n { font-variant-numeric: tabular-nums; }
.react-pill.empty-state { color: var(--ink-faint); }

.react-picker {
  /* Anchored right: the pill sits near the card's right edge now, so opening
     leftwards is what keeps the picker inside the card. */
  position: absolute; z-index: 40; bottom: calc(100% + 8px); right: 0;
  display: flex; gap: 2px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-pill); box-shadow: var(--shadow-lg);
}
.react-choice {
  font-size: 20px; line-height: 1; padding: 6px 7px; cursor: pointer;
  background: none; border: 0; border-radius: var(--r-pill);
  transition: transform .12s ease, background .12s ease;
}
.react-choice:hover { transform: scale(1.25); background: var(--brand-050); }
.react-choice.chosen { background: var(--brand-100); }
.react-choice:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.icon-btn {
  font: inherit; font-size: 12.5px; font-weight: 700; cursor: pointer;
  border: 1.5px solid var(--line); background: var(--surface); color: var(--ink-faint);
  padding: 5px 11px; border-radius: var(--r-sm); transition: all .14s ease;
}
.icon-btn:hover { border-color: var(--brand-300); color: var(--brand); background: var(--brand-050); }
.icon-btn.done { background: var(--mint-soft); border-color: var(--mint-soft); color: var(--mint); }
.icon-btn:disabled { opacity: .6; cursor: default; }

.empty {
  grid-column: 1 / -1; text-align: center; padding: 60px 20px; color: var(--ink-faint);
}
.empty strong { display: block; font-size: 19px; color: var(--ink); margin-bottom: 6px; }

.skeleton {
  height: 214px; border-radius: var(--r-lg);
  background: linear-gradient(100deg, var(--line-soft) 30%, #fff 50%, var(--line-soft) 70%);
  background-size: 220% 100%; animation: shimmer 1.3s infinite;
}
@keyframes shimmer { to { background-position: -220% 0; } }

/* ---------------------------------------------------------------- submit -- */

/* The dark band the forms sit in. A diagonal azure→teal→leaf wash rather than
   one flat colour: the three rings again, at the one place on the page big
   enough to show all three. Keep it DARK — every .field rule below is tuned for
   white-on-colour, and a light band would take the whole form with it. */
.submit-band {
  background: linear-gradient(118deg, var(--brand) 0%, var(--brand-700) 38%, #12707d 74%, #3f7a3c 100%);
  color: #fff;
  border-radius: var(--r-xl); padding: 48px 40px; margin-bottom: 64px;
  position: relative; overflow: hidden;
}
/* Three concentric rings, off the bottom-right corner, echoing the mark. */
.submit-band::after {
  content: ""; position: absolute; right: -110px; bottom: -140px;
  width: 340px; height: 340px; border-radius: 50%;
  border: 2px solid rgba(255,255,255,.14);
  box-shadow: inset 0 0 0 40px rgba(255,255,255,.05),
              0 0 0 44px rgba(255,255,255,.07);
}
.submit-band > * { position: relative; }
.submit-band h2 { font-size: clamp(26px, 4vw, 36px); }
.submit-band p.lede { color: rgba(255,255,255,.8); max-width: 470px; margin: 12px 0 0; }

.form { margin-top: 30px; display: grid; gap: 16px; max-width: 660px; }
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }

.field label {
  display: block; font-size: 13px; font-weight: 700; margin-bottom: 7px;
  color: rgba(255,255,255,.9); letter-spacing: .01em;
}
.field .hint { font-weight: 600; color: rgba(255,255,255,.55); }

.field input, .field select, .field textarea {
  width: 100%; font: inherit; font-size: 15px;
  padding: 12px 16px; border-radius: var(--r-md);
  border: 1.5px solid rgba(255,255,255,.22);
  background: rgba(255,255,255,.1); color: #fff;
}
.field textarea { resize: vertical; min-height: 84px; border-radius: var(--r-md); }
.field input::placeholder, .field textarea::placeholder { color: rgba(255,255,255,.45); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: rgba(255,255,255,.6); background: rgba(255,255,255,.16);
}
.field select option { color: var(--ink); background: #fff; }

/* ------------------------------------------------------------ emoji picker -- */

.emoji-wrap { position: relative; }
.emoji-row { display: flex; gap: 10px; align-items: center; }
.emoji-row input { flex: 1; min-width: 0; }

.emoji-trigger {
  /* Height is pinned to match the text inputs beside it. Left to shrink-wrap,
     any stray padding rule silently resizes it — which is exactly what happened
     when this modifier was called `.empty` and collided with the wall's
     "nothing here yet" placeholder and its 60px padding. */
  flex: none; width: 52px; height: 50px; padding: 0;
  font-size: 22px; line-height: 1; cursor: pointer;
  border: 1.5px solid rgba(255, 255, 255, .22);
  background: rgba(255, 255, 255, .1);
  border-radius: var(--r-md);
  transition: border-color .14s ease, background .14s ease;
}
.emoji-trigger:hover { border-color: rgba(255, 255, 255, .6); background: rgba(255, 255, 255, .18); }
.emoji-trigger.emoji-blank { opacity: .5; }
.emoji-trigger:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* The panel is always light: it sits over the indigo band on the add form and
   over white on a listing page, and one readable treatment beats two. */
.emoji-panel {
  position: absolute; z-index: 60; top: calc(100% + 8px); left: 0;
  width: min(340px, calc(100vw - 48px)); max-height: 300px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--shadow-lg);
  padding: 12px 14px;
}

.emoji-group + .emoji-group { margin-top: 12px; }
.emoji-group-name {
  font-family: var(--font-display); font-size: 10.5px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint);
  margin-bottom: 6px;
}
.emoji-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(34px, 1fr)); gap: 2px; }
.emoji-cell {
  font-size: 19px; line-height: 1; padding: 6px 0; cursor: pointer;
  background: none; border: 0; border-radius: 8px;
  transition: background .12s ease, transform .12s ease;
}
.emoji-cell:hover { background: var(--brand-050); transform: scale(1.15); }
.emoji-cell:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

/* On a white surface — the listing page edit form — the trigger needs the
   light treatment instead of the one tuned for the indigo band. */
.field.light .emoji-trigger {
  border-color: var(--line); background: var(--surface); color: var(--ink);
}
.field.light .emoji-trigger:hover { border-color: var(--brand-300); background: var(--brand-050); }
.field.light .emoji-trigger:focus-visible { outline-color: var(--brand); }

/* Honeypot — invisible to people, irresistible to form-filling bots. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-foot { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 4px; }
.btn.on-brand { background: #fff; color: var(--brand); }
.btn.on-brand:hover { background: var(--brand-050); }

.form-msg { font-size: 14.5px; font-weight: 600; }
.form-msg.err { color: #ffc9ce; }
.form-msg.ok  { color: #bff0dd; }

/* ---------------------------------------------------------------- report -- */

dialog.sheet {
  border: 0; border-radius: var(--r-lg); padding: 0;
  width: min(460px, calc(100% - 32px));
  box-shadow: var(--shadow-lg); color: var(--ink);
}
dialog.sheet::backdrop { background: rgba(28, 29, 51, .45); backdrop-filter: blur(3px); }
.sheet-in { padding: 28px; }
.sheet h3 { font-size: 20px; }
.sheet p { color: var(--ink-soft); font-size: 14.5px; margin: 10px 0 18px; }
.sheet textarea {
  width: 100%; font: inherit; font-size: 15px; padding: 12px 14px;
  border: 1.5px solid var(--line); border-radius: var(--r-md); min-height: 92px; resize: vertical;
}
.sheet textarea:focus { outline: none; border-color: var(--brand-300); box-shadow: 0 0 0 4px var(--brand-050); }
.sheet-acts { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }

.field.light label { color: var(--ink); }
.field.light .hint { color: var(--ink-faint); font-weight: 600; }
.field.light input,
.field.light select {
  border: 1.5px solid var(--line); background: var(--surface); color: var(--ink);
}
.field.light input::placeholder { color: var(--ink-faint); }
.field.light input:focus,
.field.light select:focus {
  border-color: var(--brand-300); background: var(--surface);
  box-shadow: 0 0 0 4px var(--brand-050);
}
.sheet .field { margin-bottom: 14px; }

.confirm-view { text-align: center; }
.confirm-mark {
  width: 52px; height: 52px; margin: 0 auto 18px; border-radius: 50%;
  display: grid; place-items: center; font-size: 26px; font-weight: 700;
}
.confirm-mark.good { background: var(--mint-soft); color: var(--mint); }
.confirm-mark.bad  { background: #fdeaec; color: var(--heart); }
.confirm-view p { margin: 10px 0 0; }
.confirm-view .confirm-what { color: var(--ink-faint); font-size: 13.5px; margin-top: 12px; }
.confirm-view .sheet-acts { justify-content: center; margin-top: 22px; }

.code-input {
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 26px !important; letter-spacing: .3em; text-align: center;
  font-variant-numeric: tabular-nums;
}
.tickbox {
  display: flex; gap: 10px; align-items: flex-start; margin-top: 12px;
  font-size: 13.5px; font-weight: 600; color: rgba(255,255,255,.82); cursor: pointer;
}
.tickbox input { width: auto; margin: 2px 0 0; flex: none; }

.fineprint {
  margin-top: 16px; padding: 13px 15px; background: var(--brand-050);
  border-radius: var(--r-md); font-size: 12.5px; color: var(--ink-soft); line-height: 1.5;
}

/* --------------------------------------------------------------- how-band -- */

.how { margin-bottom: 64px; }
.how h2 { font-size: clamp(24px, 3.5vw, 30px); text-align: center; }
.how > p { text-align: center; color: var(--ink-soft); max-width: 560px; margin: 12px auto 34px; }
.how-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.how-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 24px;
}
.how-card .n {
  width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
  background: var(--brand); color: #fff; font-weight: 700; font-size: 14px; margin-bottom: 14px;
}
.how-card h3 { font-size: 16.5px; margin-bottom: 7px; }
.how-card p { font-size: 14.5px; color: var(--ink-soft); margin: 0; }

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

.say { margin-bottom: 64px; }
.say-grid {
  display: grid; gap: 40px; align-items: start;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-xl); padding: 40px;
}
.say h2 { font-size: clamp(24px, 3.5vw, 30px); }
.say p { color: var(--ink-soft); margin: 14px 0 0; max-width: 40ch; }
.say .say-note { font-size: 14px; color: var(--ink-faint); }

.say-form { display: grid; gap: 14px; }
.say-form textarea {
  width: 100%; font: inherit; font-size: 15px; padding: 12px 16px;
  border: 1.5px solid var(--line); border-radius: var(--r-md); resize: vertical;
  background: var(--surface); color: var(--ink);
}
.say-form textarea:focus,
.say-form select:focus {
  outline: none; border-color: var(--brand-300); box-shadow: 0 0 0 4px var(--brand-050);
}
.say-form select {
  width: 100%; font: inherit; font-size: 15px; padding: 12px 16px;
  border: 1.5px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink);
}
.say-form .form-msg.ok { color: var(--mint); }
.say-form .form-msg.err { color: var(--heart); }

@media (max-width: 820px) {
  .say-grid { grid-template-columns: 1fr; gap: 26px; padding: 28px 22px; }
}

/* ------------------------------------------------------------------ jobs -- */

.jobs { padding: 40px 0 64px; }
/* Ranged left, like the wall's hero. These three boards are one site, and a
   centred heading under a left-ranged eyebrow reads as a mistake — which is
   exactly what it looked like when the eyebrow lost its second rule. */
.jobs-hero { padding-bottom: 30px; }
.jobs-h1 {
  font-family: var(--font-display); font-size: clamp(32px, 5.2vw, 48px);
  letter-spacing: -.035em; color: var(--brand); margin: 4px 0 0;
}
.jobs-h1 .jh-where { color: var(--teal); }
.jobs-sub { max-width: 48ch; margin: 14px 0 0; color: var(--ink-soft); font-size: 17px; }
.jobs-actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 24px; }

.jobs-search { display: flex; gap: 10px; margin-bottom: 16px; }
.jobs-search .search { flex: 1; }
.jobs-chips { margin-bottom: 26px; }
.jobs-chips .chip { text-decoration: none; }
.jobs-chips .chip.on { background: var(--brand); border-color: var(--brand); color: #fff; }

/* City comes before kind of work on both boards, and reads as the senior
   filter: larger, with a rule under it. The wall uses a segmented control for
   the same job — these are links, because both boards are server-rendered and
   have to keep working with no JavaScript at all. */
.city-chips { margin-bottom: 14px; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
.city-chips .chip { font-size: 15px; padding: 9px 18px; }
.city-chips .chip.on { background: var(--brand); border-color: var(--brand); }

.jobs-grid {
  display: grid; gap: 14px; margin-bottom: 56px;
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
}

.job-card {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 20px 20px 16px;
  display: flex; flex-direction: column;
  transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.job-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--brand-100); }

.job-top { display: flex; gap: 14px; align-items: flex-start; justify-content: space-between; }
.job-title { font-family: var(--font-display); font-size: 18px; letter-spacing: -.02em; margin: 0; }
.job-title a { color: var(--ink); text-decoration: none; }
.job-title a:hover { color: var(--brand); }
.job-employer { font-size: 14px; color: var(--ink-soft); font-weight: 600; margin-top: 3px; }
.job-employer a { color: var(--brand); text-decoration: none; }
.job-employer.big { font-size: 17px; }
.job-listed { font-size: 11.5px; color: var(--mint); font-weight: 700; }

/* Pay is the first thing anyone looks for, at either end of the board. */
.job-pay {
  flex: none; font-family: var(--font-display); font-weight: 700; font-size: 15px;
  color: var(--brand); background: var(--brand-050);
  padding: 5px 12px; border-radius: var(--r-pill); white-space: nowrap;
}
.badge.pay { background: var(--brand-050); color: var(--brand); font-size: 13px; }

.job-meta {
  display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px;
  font-size: 13px; color: var(--ink-faint); font-weight: 600;
}
.job-desc { font-size: 14.5px; color: var(--ink-soft); margin: 12px 0 0; }

.job-foot {
  margin-top: auto; padding-top: 14px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.job-age { font-size: 12.5px; color: var(--ink-faint); font-weight: 600; }
/* Tap-to-call is the whole interaction for most of this board. */
.job-call { white-space: nowrap; }

.job-page { padding: 40px 0 64px; }
.job-head h1 { font-family: var(--font-display); font-size: clamp(28px, 5vw, 40px); letter-spacing: -.03em; }
.job-body { font-size: 16.5px; line-height: 1.7; max-width: 62ch; margin: 22px 0 0; color: var(--ink-soft); }

.job-contact { margin: 32px 0 0; }
.job-call-big { font-size: 18px; padding: 15px 30px; }
.job-contact-note { font-size: 13.5px; color: var(--ink-faint); margin: 10px 0 0; }
.job-closed {
  margin: 30px 0 0; padding: 18px 20px; background: var(--sand-soft);
  border-radius: var(--r-md); color: var(--sand-ink); font-weight: 600;
}

.job-apply {
  margin: 32px 0 0; padding: 26px 28px; max-width: 520px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  display: grid; gap: 14px;
}
.job-apply h2 { font-family: var(--font-display); font-size: 20px; margin: 0; }
.job-apply textarea {
  width: 100%; font: inherit; font-size: 15px; padding: 12px 16px;
  border: 1.5px solid var(--line); border-radius: var(--r-md); resize: vertical;
}
.job-apply textarea:focus { outline: none; border-color: var(--brand-300); box-shadow: 0 0 0 4px var(--brand-050); }
.job-apply .btn { justify-self: start; }

.post-band {
  background: linear-gradient(118deg, var(--brand) 0%, var(--brand-700) 38%, #12707d 74%, #3f7a3c 100%);
  color: #fff;
  border-radius: var(--r-xl); padding: 44px 40px; margin-bottom: 20px;
  position: relative; overflow: hidden;
}
.post-band::after {
  content: ""; position: absolute; right: -110px; bottom: -140px;
  width: 340px; height: 340px; border-radius: 50%;
  border: 2px solid rgba(255,255,255,.14);
  box-shadow: inset 0 0 0 40px rgba(255,255,255,.05),
              0 0 0 44px rgba(255,255,255,.07);
}
.post-band > * { position: relative; }
.post-band h2 { font-size: clamp(26px, 4vw, 34px); }
.post-band .lede { color: rgba(255,255,255,.8); max-width: 46ch; margin: 12px 0 0; }

.contact-choice { border: 0; padding: 0; margin: 0; }
.field-note { display: block; font-size: 12.5px; color: rgba(255,255,255,.6); margin-top: 6px; }
.job-or { margin: 22px 0 0; font-size: 14.5px; color: var(--ink-faint); font-weight: 600; }
.job-cta { display: inline-flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

.contact-choice legend {
  font-size: 13px; font-weight: 700; color: rgba(255,255,255,.9); padding: 0; margin-bottom: 8px;
}

@media (max-width: 720px) {
  .post-band { padding: 30px 22px; border-radius: var(--r-lg); }
  .job-top { flex-direction: column; gap: 10px; }
  .job-pay { align-self: flex-start; }
  .jobs-search { flex-direction: column; }
}

/* ---------------------------------------------------------------- events -- */

.event-group + .event-group { margin-top: 34px; }
.event-group-name {
  font-family: var(--font-display); font-size: 13px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint);
  margin: 0 0 14px; padding-bottom: 8px; border-bottom: 1px solid var(--line);
}
.events-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
}

.event-card {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 18px 20px 16px;
  display: flex; flex-direction: column;
  transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.event-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--brand-100); }

/* The date leads: on an events board it is the first thing anyone reads. */
.event-when { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.event-date {
  font-family: var(--font-display); font-weight: 700; font-size: 13px;
  color: var(--brand); letter-spacing: -.01em;
}
.event-soon {
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--line-soft); color: var(--ink-faint);
}
.event-soon.now { background: var(--amber-soft); color: var(--amber); }
.event-when.big { margin-bottom: 10px; }
.event-when.big .event-date { font-size: 16px; }

.event-title { font-family: var(--font-display); font-size: 17.5px; letter-spacing: -.02em; margin: 8px 0 0; }
.event-title a { color: var(--ink); text-decoration: none; }
.event-title a:hover { color: var(--brand); }
.event-org { font-size: 14px; color: var(--ink-soft); font-weight: 600; margin-top: 3px; }
.event-org a { color: var(--brand); text-decoration: none; }
.event-meta {
  display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px;
  font-size: 13px; color: var(--ink-faint); font-weight: 600;
}
.event-cost { color: var(--brand); }
.event-foot { margin-top: auto; padding-top: 14px; display: flex; gap: 8px; }

/* ------------------------------------------------------------ institutes -- */
/*
 * The card answers one question for a company: can I recruit here, and who do
 * I ring? So the availability claim gets the loudest treatment on the card —
 * louder than the name — because it is the only thing on it that changes.
 */

.inst-grid {
  display: grid; gap: 14px; margin-bottom: 56px;
  grid-template-columns: repeat(auto-fill, minmax(min(330px, 100%), 1fr));
}

.inst-card {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 20px 20px 16px;
  display: flex; flex-direction: column;
  transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.inst-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--brand-100); }

.inst-top { display: flex; gap: 14px; align-items: flex-start; justify-content: space-between; }
.inst-name { font-family: var(--font-display); font-size: 18px; letter-spacing: -.02em; margin: 0; }
.inst-name a { color: var(--ink); text-decoration: none; }
.inst-name a:hover { color: var(--brand); }

.inst-meta {
  display: flex; gap: 12px; flex-wrap: wrap; margin-top: 8px;
  font-size: 13px; color: var(--ink-faint); font-weight: 600;
}
.inst-meta.big { margin-top: 12px; font-size: 14.5px; }

.inst-courses { font-size: 14.5px; color: var(--ink-soft); margin: 12px 0 0; }

/* The perishable fact, and the reason this board is worth visiting twice.
   A confirmed claim is green and carries its own age; an unconfirmed one is
   quiet grey rather than red — "we have not heard lately" is not a fault. */
.inst-claim {
  margin: 14px 0 0; padding: 9px 12px;
  border-radius: var(--r-sm); font-size: 13px; font-weight: 700;
}
.inst-claim.yes { background: var(--teal-soft); color: var(--teal); }
.inst-claim.no  { background: var(--line-soft); color: var(--ink-faint); }
.inst-claim.big { font-size: 15px; padding: 12px 16px; margin: 22px 0 0; max-width: 60ch; }

.inst-foot {
  margin-top: auto; padding-top: 14px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
}
.inst-who { font-size: 12.5px; color: var(--ink-soft); font-weight: 700; min-width: 0; }
.inst-who.none { color: var(--ink-faint); font-weight: 600; }
.inst-cta { display: inline-flex; gap: 6px; flex-wrap: wrap; }

.inst-block { margin: 32px 0 0; }
.inst-block h2 { font-family: var(--font-display); font-size: 20px; margin: 0 0 8px; }

/* ----------------------------------------------------------- experts -- */

.exp-grid {
  display: grid; gap: 14px; margin-bottom: 56px;
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
}

.exp-card {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 20px 20px 16px;
  display: flex; flex-direction: column;
  transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.exp-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--brand-100); }

.exp-top { display: flex; gap: 14px; align-items: flex-start; justify-content: space-between; }
.exp-name { font-family: var(--font-display); font-size: 18px; letter-spacing: -.02em; margin: 0; }
.exp-name a { color: var(--ink); text-decoration: none; }
.exp-name a:hover { color: var(--brand); }
.exp-headline { font-size: 14.5px; color: var(--ink-soft); margin: 4px 0 0; }
.exp-headline.big { font-size: 18px; margin-top: 10px; max-width: 60ch; }

/* Sits in the tag row, and WRAPS. A rate here is free text and routinely a
   whole sentence, so nowrap would either overflow the card or crush whatever
   shares its line. */
.exp-rate {
  font-family: var(--font-display); font-weight: 700; font-size: 12px;
  color: var(--brand); background: var(--brand-050);
  padding: 4px 10px; border-radius: var(--r-pill);
}
.exp-rate-inline { color: var(--brand); }

.exp-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
.exp-tags.big { margin-top: 14px; }
.exp-tag {
  font-size: 11.5px; font-weight: 700; letter-spacing: .03em;
  padding: 4px 10px; border-radius: var(--r-pill);
  background: var(--line-soft); color: var(--ink-soft);
}
/* Free help is the reason a lot of people open this board at all, so it is the
   one tag that gets a colour. Leaf, not the brand azure: it should read as
   generosity rather than as the site's own chrome. */
.exp-tag.free { background: var(--leaf-soft); color: var(--leaf); }

.exp-meta {
  display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px;
  font-size: 13px; color: var(--ink-faint); font-weight: 600;
}
.exp-meta.big { margin-top: 14px; font-size: 14.5px; }

.exp-foot { margin-top: auto; padding-top: 14px; display: flex; gap: 8px; }

/* The "this is for adding YOURSELF" note, on the dark band. It is the one piece
   of copy on the site that has to be read before the form below it, so it is
   given a panel rather than being set as a hint. */
.exp-selfnote {
  margin: 0 0 4px; padding: 14px 16px;
  background: rgba(255, 255, 255, .12);
  border-left: 3px solid rgba(255, 255, 255, .5);
  border-radius: var(--r-sm);
  font-size: 14px; line-height: 1.55; color: rgba(255, 255, 255, .88);
}
.exp-selfnote strong { color: #fff; }

/* The free-help toggle in the hero is a link, not a chip, so it needs the
   pressed state spelled out. */
.jobs-actions .btn.ghost.on {
  background: var(--leaf-soft); color: var(--leaf); border-color: var(--leaf);
}

@media (max-width: 720px) {
  .inst-top { flex-direction: column; gap: 10px; }
  .inst-foot { align-items: flex-start; }
}

/* ---------------------------------------------------------------- cowork -- */
/*
 * A card answers: where, what can I book, what does it cost, and will the power
 * stay on. The price line always carries its age; an old price turns quiet grey
 * rather than disappearing, because a dated old price is still more use than
 * none.
 */

.cw-grid {
  display: grid; gap: 14px; margin-bottom: 56px;
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
}

.cw-card {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 20px 20px 16px;
  display: flex; flex-direction: column;
  transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.cw-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--brand-100); }

.cw-name { font-family: var(--font-display); font-size: 18px; letter-spacing: -.02em; margin: 0; }
.cw-name a { color: var(--ink); text-decoration: none; }
.cw-name a:hover { color: var(--brand); }

.cw-meta {
  display: flex; gap: 12px; flex-wrap: wrap; margin-top: 8px;
  font-size: 13px; color: var(--ink-faint); font-weight: 600;
}
.cw-meta.big { margin-top: 12px; font-size: 14.5px; }

.cw-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
.cw-tags.big { margin-top: 14px; }
.cw-tag {
  font-size: 11.5px; font-weight: 700; letter-spacing: .03em;
  padding: 4px 10px; border-radius: var(--r-pill);
  background: var(--line-soft); color: var(--ink-soft);
}
/* The day pass is what a visitor from another city is looking for, so it is
   the one offer with a colour. Facilities get a quieter outline — they are
   answers to a question, not things you book. */
.cw-tag.pass { background: var(--brand-050); color: var(--brand); }
.cw-tag.facility { background: none; border: 1px solid var(--line); color: var(--ink-faint); }

.cw-price {
  margin: 14px 0 0; padding: 9px 12px;
  border-radius: var(--r-sm); font-size: 13px; font-weight: 700;
  background: var(--leaf-soft); color: var(--leaf);
}
.cw-price.stale, .cw-price.none { background: var(--line-soft); color: var(--ink-faint); }
.cw-price.big { font-size: 15px; padding: 12px 16px; margin: 22px 0 0; max-width: 60ch; }

.cw-hours { font-size: 13px; color: var(--ink-soft); margin: 10px 0 0; }

.cw-foot { margin-top: auto; padding-top: 14px; display: flex; gap: 8px; flex-wrap: wrap; }

/* ------------------------------------------------------------- editing -- */
/*
 * The in-page edit form, on every board's detail page — the wall's listing
 * edit panel. These rules used to be inline in the listing page, so when the
 * other boards grew an edit form it rendered unstyled; the same was quietly
 * true of .made-strip on every non-listing detail page.
 */
.edit-panel {
  margin-top: 34px; padding: 26px 28px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  display: grid; gap: 14px; max-width: 620px;
}
.edit-panel h2 { font-family: var(--font-display); font-size: 20px; }
.edit-panel .edit-note { color: var(--ink-soft); font-size: 14.5px; margin: -4px 0 4px; }
.edit-panel textarea {
  width: 100%; font: inherit; font-size: 15px; padding: 12px 16px;
  border: 1.5px solid var(--line); border-radius: var(--r-md); resize: vertical;
}
.edit-panel textarea:focus {
  outline: none; border-color: var(--brand-300); box-shadow: 0 0 0 4px var(--brand-050);
}
/* .tickbox is styled for the dark add-form band; on the white edit panel it
   needs ink-coloured text. */
.edit-panel .tickbox { color: var(--ink-soft); margin-top: 0; }

.edit-cta {
  margin-top: 30px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  font-size: 14px; font-weight: 600; color: var(--ink-faint);
}

.made-strip {
  margin-top: 40px; padding-top: 22px; border-top: 1px dashed var(--line);
  display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; align-items: center;
}

/* ---------------------------------------------------------------- footer -- */

/* The footer is the mark, the name and the three cities, side by side rather
   than stacked in the middle — the same ranged-left rhythm as the hero, so the
   page opens and closes the same way. */
.site-footer {
  position: relative; background: var(--surface);
  border-top: 1px solid var(--line);
  padding: 48px 0 40px;
}
.site-footer::before {
  content: ""; position: absolute; left: 0; right: 0; top: -1px;
  height: 3px; background: var(--rings);
}
.footer-top {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding-bottom: 22px; border-bottom: 1px solid var(--line-soft);
}
.footer-mark { width: 54px; height: 54px; display: block; flex: none; }
.footer-word { font-family: var(--font-display); font-size: 27px; font-weight: 700; color: var(--brand); letter-spacing: -.035em; line-height: 1.1; }
.footer-word .wm-b { color: var(--teal); }
.footer-boards { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.footer-boards a {
  font-family: var(--font-display); font-weight: 700; font-size: 14px;
  color: var(--ink-soft); text-decoration: none;
  padding: 8px 14px; border-radius: var(--r-sm);
}
.footer-boards a:hover { background: var(--brand-050); color: var(--brand); }

.footer-cities {
  display: flex; gap: 8px 22px; flex-wrap: wrap; margin-top: 22px;
  font-family: var(--font-display); font-weight: 700; font-size: 15px; color: var(--ink-soft);
}
.footer-cities span { display: inline-flex; align-items: center; gap: 8px; }
.footer-cities .cd { width: 9px; height: 9px; border-radius: 50%; }
.footer-cities span:nth-of-type(1) .cd { background: var(--azure); }
.footer-cities span:nth-of-type(2) .cd { background: var(--teal); }
.footer-cities span:nth-of-type(3) .cd { background: var(--leaf); }

.footer-note { margin-top: 18px; font-size: 12.5px; color: var(--ink-faint); max-width: 62ch; }

@media (max-width: 720px) {
  .footer-boards { margin-left: 0; width: 100%; }
  .footer-boards a { padding: 8px 12px; }
}

/* --------------------------------------------------------------- responsive */

/* ================================================== two-row header ===
   The header is ONE row only while one row fits, and with six boards that is
   measured, not guessed: brand 224px + boards + Add 92px + gaps needs 888px
   of page width (it was 802px with five). Below that the row wraps, and
   without this block it wrapped by accident — brand alone on top, boards and
   Add jammed onto a second line with desktop sizing, at any tablet width.

   The breakpoint is 920, not 888, because a media query measures the VIEWPORT
   and the header lays out in the PAGE — which is 15px narrower wherever the
   browser draws a classic scrollbar (Windows, most Linux). At a 901px viewport
   that leaves 886px, under the 888 a row needs, and the header wrapped by
   accident in a thin band. 920 covers the scrollbar with a little to spare.

   So below 920px the header is two rows on purpose:

     row 1   [mark] HDB Connect                        [Add yours]
     row 2   Wall  Jobs  Events  Institutes  Experts  CoWork

   Every board stays visible, nothing scrolls sideways, and there is still no
   hamburger — the site's hardest problem is people not knowing the other
   boards exist, and six destinations behind a menu is that problem with a lid
   on. See invariant 13. */
@media (max-width: 920px) {
  .site-header .wrap { min-height: 0; gap: 8px 10px; padding-top: 9px; padding-bottom: 7px; }
  .board-nav {
    order: 3; flex: 1 0 100%;
    display: flex; gap: 2px;
    /* Without this the nav's automatic minimum is the sum of its labels, so a
       row that runs out of room pushes the whole nav off the screen instead of
       letting the links shrink. That is exactly what six labels at 320px did —
       20px over, with the right edge 4px past the viewport — while the comment
       below promised an ellipsis. */
    min-width: 0;
    /* Labels take their NATURAL width and the leftover space goes into the
       gaps. An equal share starves the longest label: at flex: 1 1 0 every
       board got 56px, which clipped "Institutes" while "Jobs" sat in twice
       the room it needed. */
    justify-content: space-between;
  }
  .board-link {
    flex: 0 1 auto; min-width: 0;
    /* If a longer board name is ever added and the row does run out, it now
       genuinely fails here — with an ellipsis — rather than running off the
       edge. Measure before relying on it; it is a safety net, not a layout. */
    overflow: hidden; text-overflow: ellipsis;
  }
  .header-add { margin-left: auto; }
}


@media (max-width: 720px) {
  .wrap { width: calc(100% - 32px); }
  .hero { padding: 40px 0 30px; }
  .row2 { grid-template-columns: 1fr; }
  .submit-band { padding: 34px 24px; border-radius: var(--r-lg); }
  /* Phone sizing for the board row. The row itself — wrapping, full width,
     natural label widths — starts at 900px; see the "two-row header" block
     above. Here it only gets smaller type and tighter padding. */
  .board-link { padding: 8px 5px; font-size: 13px; letter-spacing: -.01em; }
  /* The three cities under the wordmark are the first thing to go when space
     is tight — row 2 names the boards, and the hero names the cities. */
  .brand-tag { display: none; }
  .brand img { width: 34px; height: 34px; }
  .brand { gap: 9px; }
  .brand-name { font-size: 17px; white-space: nowrap; }
  /* The board eyebrow wraps rather than clipping.
     `.be-text` is nowrap so the trailing rule stays welded to the last word —
     correct on a wide screen, and at 320px it ran "Institutes in Hubballi,
     Dharwad & Belagavi" 69px past the edge, where it was silently cut to
     "…& BE". Wrapped text with no rule beats a clipped line with one, so the
     rule goes and the words break. */
  .board-eyebrow { flex-wrap: wrap; }
  .be-text { white-space: normal; margin-right: 0; }
  .be-line { display: none; }

  /* Long labels get a short form on a narrow screen. Namespaced: `.long` and
     `.short` are exactly the kind of generic names that collide with something
     unrelated later. */
  .nav-short { display: inline; }
  .nav-long { display: none; }
}
/* The narrowest phones. This block MUST come after the 720px block: both set
   .board-link padding and font-size at the same specificity, so whichever is
   later in the file wins. It was first placed above it, and silently did
   nothing — the measurement caught it, not the test.

    Six labels need 308px at 13px with 5px padding, and a
   320px screen leaves 288px, so below 360px the type drops half a point and the
   padding tightens: measured, that lands them with room to spare. 360px and up
   — nearly every Android, every iPhone — keeps the regular sizing. */
@media (max-width: 359px) {
  .board-link { padding: 8px 3px; font-size: 12.5px; letter-spacing: -.015em; }
}

@media (min-width: 721px) {
  .nav-short { display: none; }
  .nav-long { display: inline; }
}

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