/* ============================================================
   Barangay Monte Alegre, Municipality of Kananga — Public Services Website
   Palette: Primary #215294 · Secondary #ECF4FF · Ink #18233F · White
   Type:    Zilla Slab (display) · Public Sans (body) · IBM Plex Mono (utility)
   ============================================================ */

:root {
  --paper: #FFFFFF;        /* Background */
  --paper-deep: #ECF4FF;   /* Secondary — alternating bands, fills */
  --folder: #C7D9F1;       /* Folder behind the certificate mock */
  --white: #FFFFFF;
  --ink: #18233F;          /* Text primary / links */
  --ink-soft: #55617D;
  --line: #D5E2F3;
  --blue: #215294;         /* Primary / accent */
  --blue-dark: #17406F;    /* Primary, pressed / hovered */
  --blue-deep: #18233F;    /* Deep surfaces: govbar, hero, footer */
  --blue-wash: #ECF4FF;    /* Secondary */
  --sky: #A9C7EE;          /* Accent for text on deep surfaces */
  --focus: #4F86D6;        /* Focus ring — legible on white and on navy */

  /* The national colours, fixed by RA 8491 (Flag and Heraldic Code). These
     are the flag's own hues, not the site palette — they are never tinted
     to match the letterhead blue. */
  --ph-blue: #0038A8;
  --ph-red: #CE1126;
  --ph-gold: #FCD116;

  --font-display: "Zilla Slab", "Rockwell", "Georgia", serif;
  --font-body: "Public Sans", "Segoe UI", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", "Consolas", "Courier New", monospace;
  /* One line uses this — the motto in the footer rule. */
  --font-script: "Brush Script MT", "Segoe Script", cursive;

  --radius: 6px;
  --shadow-paper: 0 1px 2px rgba(24, 35, 63, 0.06), 0 8px 24px rgba(24, 35, 63, 0.08);
  --shadow-lift: 0 2px 4px rgba(24, 35, 63, 0.18), 0 24px 48px rgba(24, 35, 63, 0.34);
  /* The container runs the full viewport; the gutter is what keeps content
     off the edges, and it widens with the screen instead of the container
     stopping at a fixed width and leaving rails of empty paper. */
  --wrap: 100%;
  --gutter: 24px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* scroll-padding keeps anchor targets clear of the sticky masthead */
html { scroll-behavior: smooth; scroll-padding-top: 104px; }

/* Host styles for Lenis smooth scrolling (initialised in js/main.js).
   When Lenis drives the scroll it owns the easing, so the CSS smooth
   behavior steps aside to avoid double-easing every programmatic jump. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

body {
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

img, svg { max-width: 100%; display: block; }

a { color: var(--ink); }
/* :not(.btn) so a link styled as a button keeps its own text colour on
   hover — otherwise a solid blue button turns blue-on-blue */
a:not(.btn):hover { color: var(--blue); }

/* removes the legacy 300ms tap delay on touch devices */
a, button, summary, label { touch-action: manipulation; }

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}

.wrap {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--blue);
  color: #fff;
  padding: 10px 18px;
  font-weight: 700;
  z-index: 200;
}
.skip-link:focus { left: 12px; top: 12px; }

/* ---------- Off-page SVG sprites ----------
   The two empty seal slots, drawn once as <symbol>s and referenced
   wherever a seal goes until the hall has uploaded one. Their container is a zero-sized <svg> that must not take part
   in layout — it sat on a style="position:absolute" attribute until the
   Content-Security-Policy went in, and now that the policy refuses
   inline styles outright it lives here. Three declarations rather than
   one, because a zero-height box can still contribute a text baseline. */
.svg-sprite {
  position: absolute;
  width: 0;
  height: 0;
}

/* ---------- A seal the hall has uploaded ----------
   The <symbol>s above hold the place. Once the hall has uploaded its own
   at Site details, js/main.js puts an <img> in the same place wearing the
   same class list, so every rule that sized that square goes on sizing it
   and nothing below here has to know which of the two it got.

   These are the only two things that are true of a photograph and not of
   the drawing. */

/* Arms are never cropped. Cloudinary already pads the upload out to a
   square; this is what holds if it ever does not. */
img.seal { object-fit: contain; }

/* On a dark ground, a seal gets what a printed one gets on a dark
   tarpaulin: a light disc under it.

   The empty ring needs no such thing — it is stroked in currentColor and
   takes each ground's own palette with it. A photograph does not. What a
   barangay has on file is almost always a scan on white paper, and
   dropped straight into the footer that is a white postage stamp stuck
   to the page. The disc
   is the fix and the crop is part of it: a barangay seal is a circle, so
   rounding the box off clips away the white corners of the scan and
   leaves the arms in a field of their own. Anything the upload does not
   cover, the white behind it does.

   The padding is what keeps it a mount rather than a frame — a hair of
   white all the way round, so the arms read as set on the disc instead
   of trimmed by it. In pixels, not the percent this first asked for: a
   percentage padding resolves against the containing block's width and
   not the box's own, so 5% here measured 5% of the footer column and
   drew a 22% ring. Every seal on the site is sized in pixels by the rule
   that places it, so this can be too. */
.footer img.seal {
  background: #fff;
  border-radius: 50%;
  padding: 3px;
}

/* ---------- Brand stripe ---------- */
.flag-stripe {
  height: 4px;
  background: var(--blue);
}

/* ---------- GovPH strip ---------- */
.govbar {
  background: var(--blue-deep);
  color: #C7D4EE;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
}
.govbar .wrap {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-block: 7px;
}
/* The flag is drawn in SVG (see the markup) so it keeps its own 1:2
   proportion, its blue-over-red fields and the sun and three stars. */
.govbar .mini-flag {
  width: 26px;
  height: 13px;
  flex: none;
  border-radius: 1px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.24);
}
.govbar .gov-link {
  margin-left: auto;
  color: #C7D4EE;
  text-decoration: none;
  font-weight: 600;
}
.govbar .gov-link:hover { color: #fff; }

/* ---------- Masthead / letterhead ---------- */
.masthead {
  background: var(--white);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 110;
  transition: box-shadow 0.25s ease;
}
/* once the page is scrolled the letterhead floats, so it casts a shadow */
.masthead.scrolled { box-shadow: 0 6px 24px rgba(24, 35, 63, 0.12); }
.masthead .wrap {
  display: flex;
  align-items: center;
  gap: 18px;
  padding-block: 16px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 14px;
  /* shrinkable, so a narrow screen squeezes the letterhead instead of
     widening the page under it */
  flex: 0 1 auto;
  min-width: 0;
  text-decoration: none;
  color: var(--ink);
}
.brand .seal { width: 58px; height: 58px; flex: none; }
.brand-lines { display: block; min-width: 0; }
.brand-lines > span { display: block; white-space: nowrap; }
.brand-lines .republic {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.brand-lines .bname {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.5rem;
  line-height: 1.15;
  letter-spacing: 0.01em;
}
.brand-lines .locality {
  font-size: 0.8rem;
  color: var(--ink-soft);
}

/* City seal closes the letterhead on the right, opposite the barangay seal.
   It is a link out to the city's own site, so it gets a quiet lift on hover —
   enough to read as clickable without competing with the nav beside it. */
.masthead-mark {
  flex: none;
  display: flex;
  align-items: center;
  margin-left: 18px;
  padding-left: 18px;
  border-left: 1px solid var(--line);
}
.masthead-mark .seal {
  width: 54px;
  height: 54px;
  display: block;
  transition: transform 0.2s ease, filter 0.2s ease;
}
.masthead-mark:hover .seal,
.masthead-mark:focus-visible .seal {
  transform: scale(1.05);
  filter: drop-shadow(0 2px 6px rgba(24, 35, 63, 0.28));
}
@media (prefers-reduced-motion: reduce) {
  .masthead-mark .seal { transition: none; }
  .masthead-mark:hover .seal,
  .masthead-mark:focus-visible .seal { transform: none; }
}

.nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 4px;
}
/* :not(.btn) so the call to action inside the nav keeps its own colour,
   padding and hover state instead of being restyled as a plain link */
.nav a:not(.btn) {
  text-decoration: none;
  color: var(--ink);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 8px 14px;
  border-radius: var(--radius);
  transition: background-color 0.15s ease, color 0.15s ease;
}
.nav a:not(.btn):hover { background: var(--blue-wash); }
.nav a.active {
  color: var(--blue);
  box-shadow: inset 0 -3px 0 var(--blue);
  border-radius: 0;
}
.nav .btn { margin-left: 10px; white-space: nowrap; }

.nav-toggle {
  display: none;
  margin-left: auto;
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  /* 44px minimum: this is the only way into the menu on a phone */
  min-height: 44px;
  padding: 8px 14px;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  cursor: pointer;
  color: var(--ink);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.98rem;
  text-decoration: none;
  text-align: center;
  border-radius: var(--radius);
  padding: 12px 22px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
}
/* press feedback: the button gives slightly under the finger */
.btn:active { transform: translateY(0) scale(0.98); }
/* Light button — for use on the navy hero and footer */
.btn-light {
  background: var(--paper-deep);
  color: var(--blue-deep);
}
.btn-light:hover {
  background: #fff;
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(10, 18, 38, 0.4);
}
.btn-blue {
  background: var(--blue);
  color: #fff;
}
.btn-blue:hover { background: var(--blue-dark); transform: translateY(-1px); }
.btn-ghost {
  border-color: rgba(255, 255, 255, 0.5);
  color: #fff;
}
.btn-ghost:hover { border-color: var(--sky); color: var(--sky); }
.btn-outline {
  border-color: var(--blue);
  color: var(--blue);
  background: transparent;
}
.btn-outline:hover { background: var(--blue-wash); }

/* ---------- Bilingual signage eyebrow ---------- */
.eyebrow {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--blue);
  border: 1.5px solid currentColor;
  border-radius: 3px;
  padding: 4px 10px;
  margin-bottom: 14px;
}
.eyebrow.on-dark { color: var(--sky); }

h1, h2, h3 { font-family: var(--font-display); line-height: 1.12; }

.section { padding-block: 72px; }
.section-head { max-width: 640px; margin-bottom: 36px; }
.section-head h2 {
  font-size: clamp(1.7rem, 3.4vw, 2.4rem);
  font-weight: 700;
  margin-bottom: 10px;
}
.section-head p { color: var(--ink-soft); }

/* ---------- Ylang-ylang ground ----------
   The banner motif: Cananga odorata in line art — six strap petals hanging
   from a calyx, and the broad wavy-edged leaves. One tile serves every
   surface. It is applied as a mask, so each band picks its own paint: white
   on the navy hero, ink on the pale bands. */
.hero,
.page-hero,
.section-alt { position: relative; }

.hero > .wrap,
.page-hero > .wrap,
.section-alt > .wrap { position: relative; }

@supports ((mask-image: url("../img/ylang-ylang.svg")) or (-webkit-mask-image: url("../img/ylang-ylang.svg"))) {
  .hero::before,
  .page-hero::before,
  .section-alt::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    -webkit-mask: url("../img/ylang-ylang.svg") center / 620px 620px repeat;
    mask: url("../img/ylang-ylang.svg") center / 620px 620px repeat;
  }
  .hero::before { background: #fff; opacity: 0.06; }
  .section-alt::before { background: var(--blue); opacity: 0.13; }

  /* The banner band carries the motif hardest, but it clears out of the
     column the heading and lede occupy — a second gradient mask intersects
     the first, so no line ever crosses body copy at full strength. */
  .page-hero::before {
    background: var(--blue);
    opacity: 0.26;
    -webkit-mask-image: url("../img/ylang-ylang.svg"),
      linear-gradient(100deg, transparent 6%, rgba(0, 0, 0, 0.28) 38%, #000 68%);
    mask-image: url("../img/ylang-ylang.svg"),
      linear-gradient(100deg, transparent 6%, rgba(0, 0, 0, 0.28) 38%, #000 68%);
    -webkit-mask-size: 460px 460px, cover;
    mask-size: 460px 460px, cover;
    -webkit-mask-repeat: repeat, no-repeat;
    mask-repeat: repeat, no-repeat;
    -webkit-mask-position: center, center;
    mask-position: center, center;
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
  }
  /* Copy runs the full width below 960px, so the band steps back. */
  @media (max-width: 960px) {
    .page-hero::before { opacity: 0.13; }
  }
}

/* ---------- Hero ---------- */
.hero {
  background:
    radial-gradient(52rem 30rem at 78% 20%, rgba(169, 199, 238, 0.16), transparent 60%),
    linear-gradient(180deg, var(--blue-deep), #1D4176);
  color: #fff;
  overflow: hidden;
}
.hero .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: 56px;
  align-items: center;
  padding-block: 80px;
}
.hero h1 {
  font-size: clamp(2.4rem, 5.4vw, 3.6rem);
  font-weight: 700;
  margin-bottom: 6px;
}
.hero .h1-sub {
  display: block;
  font-size: clamp(1.35rem, 2.8vw, 1.9rem);
  font-weight: 600;
  color: #BFD0F0;
  margin-top: 6px;
}
.hero .lede {
  margin-top: 16px;
  max-width: 46ch;
  color: #D4DEF4;
  font-size: 1.08rem;
}
.hero-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 28px;
}
.hero-hours {
  margin-top: 34px;
  padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.03em;
  color: #AFC2E8;
  line-height: 1.9;
}
.hero-hours strong { color: var(--sky); font-weight: 600; }

/* Certificate mock — the signature element */
.cert-stage {
  position: relative;
  min-height: 540px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* one scale for the whole mock (widescreen bumps it), one lift for hover */
  --cert-scale: 1;
  --cert-lift: 0px;
}
/* the sheet eases out of its folder when the cursor passes over the desk */
.cert-stage:hover { --cert-lift: -10px; }
.cert-folder {
  position: absolute;
  width: 372px;
  height: 484px;
  background: var(--folder);
  border-radius: 4px 14px 4px 4px;
  transform: rotate(-3deg) translate(-14px, 14px) scale(var(--cert-scale));
  box-shadow: 0 18px 40px rgba(4, 16, 42, 0.4);
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.cert-folder::before {
  content: "";
  position: absolute;
  top: -12px;
  left: 22px;
  width: 110px;
  height: 26px;
  background: var(--folder);
  border-radius: 6px 6px 0 0;
}
/* Short bond paper is 8.5 x 11, so the sheet is held to that ratio rather
   than left to collapse around its content. */
.cert-paper {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 340px;
  min-height: 440px;
  background: var(--white);
  color: var(--ink);
  padding: 26px 26px 30px;
  transform: rotate(1.6deg) translateY(var(--cert-lift)) scale(var(--cert-scale));
  box-shadow: var(--shadow-lift);
  border-radius: 2px;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
/* Both seals flank the letterhead, barangay left and city right, the way
   they sit on the real paper. The centre column is what's left of 340px
   after them, so the type below is set to fit that width without wrapping. */
.cert-letterhead {
  display: grid;
  grid-template-columns: 34px 1fr 34px;
  align-items: center;
  gap: 8px;
  text-align: center;
  border-bottom: 2px solid var(--ink);
  padding-bottom: 12px;
}
.cert-letterhead .seal { width: 34px; height: 34px; display: block; }
.cert-letterhead .lh-line {
  font-family: var(--font-mono);
  /* "Municipality of Kananga · Province of Leyte" is a third longer than
     the line this was set for, on paper 285px wide. It comes down in size
     rather than breaking into a third line under the seals. */
  font-size: 0.43rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  line-height: 1.7;
}
.cert-letterhead .lh-brgy {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  color: var(--blue);
  margin-top: 2px;
}
.cert-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.3rem;
  letter-spacing: 0.14em;
  text-align: center;
  margin: 18px 0 14px;
}
.cert-body .line {
  height: 7px;
  border-radius: 3px;
  background: var(--paper-deep);
  margin-bottom: 9px;
}
.cert-body .line.w80 { width: 80%; }
.cert-body .line.w90 { width: 90%; }
.cert-body .line.w60 { width: 60%; }
/* Signs off at the foot of the sheet, level with the dry-seal ring */
.cert-sig {
  margin-top: auto;
  margin-left: auto;
  margin-bottom: 30px;
  width: 55%;
  text-align: center;
}
.cert-sig .sig-rule { border-top: 1.5px solid var(--ink); padding-top: 5px; }
.cert-sig .sig-name {
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.cert-sig .sig-role {
  font-family: var(--font-mono);
  font-size: 0.52rem;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.cert-dryseal {
  position: absolute;
  bottom: 26px;
  left: 24px;
  width: 84px;
  height: 84px;
  border: 2px solid rgba(33, 82, 148, 0.32);
  border-radius: 50%;
  display: grid;
  place-items: center;
}
.cert-dryseal::before {
  content: "";
  width: 62px;
  height: 62px;
  border: 1px solid rgba(33, 82, 148, 0.32);
  border-radius: 50%;
}
.stamp {
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blue);
  border: 3px double var(--blue);
  border-radius: 4px;
  padding: 6px 14px;
  display: inline-block;
  opacity: 0.9;
  background: rgba(255, 255, 255, 0.6);
}
/* Only the certificate's is a rubber stamp struck onto paper, so it is the
   only one that tilts. A tag over a notice is a label, and labels are set
   square. */
.cert-paper .stamp {
  position: absolute;
  top: 186px;
  right: -20px;
  font-size: 0.78rem;
  transform: rotate(-7deg);
}

/* ---------- Bulletin / announcements ----------
   The board is a run of cards of one shape — a photograph if the notice
   has one, the date it went up, what it is called, and the first thing it
   says. A notice is not more important because it is longer, so nothing
   here sizes a card by its contents. */
.bulletin-grid {
  display: grid;
  /* The track count follows the width available rather than a breakpoint:
     at 290px a card still holds "AUG 10, 2026" beside its chip on one
     line, which is the narrowest the meta row reads well at. */
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: 28px;
  /* Cards end where they end. Now that a photograph keeps its own shape,
     a notice with a poster on it is genuinely taller than one with a
     group shot, and stretching the short ones to match would open a hole
     between the last line and the cue that reads as something failing to
     load. A board is a thing pinned at uneven depths anyway. */
  align-items: start;
}

.notice-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-paper);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.notice-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }

/* The pinned notice is the one in the middle of the board at the hall.
   One blue rule along its top: enough to find it first, not so much that
   the rest of the board reads as an afterthought. */
.notice-card.is-pinned { border-top: 4px solid var(--blue); }

/* A posted photograph — the poster taped beside the notice.
   The card itself is deliberately NOT overflow:hidden: an outline is
   clipped by an overflowing ancestor, and the focus ring on the title is
   drawn over the whole card. So the figure clips itself instead.

   The frame is the shape of the picture in it. `--shot` is that shape,
   written on the figure by main.js as width over height, and the two
   bounds here are the only thing this page insists on: past 3:4 upright a
   single card would set the height of every card beside it, and past 5:2
   across a photograph thins to a strip and reads as a broken image.
   Between them — which is every phone photograph, every printed advisory
   and every scan — nothing is added and nothing is taken away. Outside
   them the picture is still whole, resting on the wash.

   With no `--shot` at all the declaration falls back to `auto` and the
   picture sizes itself, which is what a notice posted before the hall
   recorded sizes does until main.js has measured it. */
.notice-figure {
  position: relative;
  margin: 0;
  flex: none;
  aspect-ratio: clamp(0.75, var(--shot), 2.5);
  background: var(--blue-wash);
  border-bottom: 1px solid var(--line);
  border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0;
  overflow: hidden;
}
.notice-figure img {
  display: block;
  width: 100%;
  height: 100%;
  /* never `cover`: the top of a printed advisory is the part that says
     what it is */
  object-fit: contain;
}
/* A notice can carry a run of photographs. The card shows the cover; this
   says how many more are behind it. */
.notice-count {
  position: absolute;
  right: 10px;
  bottom: 10px;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--white);
  background: rgba(24, 35, 63, 0.78);
  padding: 4px 8px;
  border-radius: 3px;
}

.notice-card-body {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 20px 22px 0;
  flex: 1;
}
.notice-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0;
}
.notice-date {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
}
.cal-glyph {
  width: 13px;
  height: 13px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.35;
  stroke-linecap: round;
}
.notice-card h3 { font-size: 1.12rem; line-height: 1.35; }
.notice-excerpt p {
  color: var(--ink-soft);
  font-size: 0.94rem;
  line-height: 1.6;
  /* three lines of every notice, so a long first paragraph cannot push
     the cards in its row out of step */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ---------- Opening a notice ----------
   Every post on the board comes down off it to be read in full. The title
   is the control; its ::after is stretched over the whole card, so the card
   is one large target while only the title sits in the tab order. */
.notice-open {
  font: inherit;
  color: inherit;
  /* the board would read as a wall of underlines otherwise; the rule joins
     on hover and focus, as .svc-link does elsewhere on the site */
  text-decoration: none;
  transition: color 0.15s ease;
}
.notice-open::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
}
.notice-card:hover .notice-open,
.notice-open:focus-visible { color: var(--blue); text-decoration: underline; }
.notice-open:focus-visible { outline: none; }
.notice-open:focus-visible::after {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
}

/* The board's own cue that there is more paper behind the summary. The
   title link is the real control, so this is scenery — and it sits on the
   foot of the card, after a rule, so every card ends on the same line
   whatever its summary ran to. */
.notice-cue {
  display: block;
  margin: 16px 22px 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blue);
}
.notice-cue::after { content: " →"; }
.notice-card:hover .notice-cue { color: var(--blue-dark); }

/* What the board says when it has nothing to say — and what it says when
   it could not be asked. Both are sentences, not a blank panel under a
   heading. */
.bulletin-note {
  max-width: 62ch;
  margin-inline: auto;
  padding: 28px 26px;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  background: var(--blue-wash);
  color: var(--ink-soft);
  text-align: center;
}

.chip {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border: 1px solid var(--ink-soft);
  color: var(--ink-soft);
  border-radius: 3px;
  padding: 2px 8px;
  margin-bottom: 6px;
}
.chip.health { border-color: var(--blue); background: var(--blue-wash); color: var(--blue); }
.chip.event { border-color: var(--blue-deep); color: var(--blue-deep); }

/* ---------- A notice, read in full (notice.html) ----------
   The board carries index lines; opening one hands you the sheet itself, on
   its own page and at its own address, so a notice can be shared, printed
   and reopened. Official notices arrive on the barangay's letterhead, the
   same device the hall prints above a posted order. */
.notice-page {
  background: var(--paper-deep);
  border-bottom: 1px solid var(--line);
  padding-block: 26px 68px;
}
/* The container runs full-bleed; a document does not. */
.notice-page .wrap > * {
  max-width: 760px;
  margin-inline: auto;
}

.notice-sheet {
  background: var(--white);
  border: 1px solid var(--line);
  border-top: 5px solid var(--blue);
  border-radius: var(--radius);
  box-shadow: var(--shadow-paper);
  padding: 34px 40px 40px;
}
.notice-sheet .stamp { font-size: 0.7rem; margin-bottom: 14px; }
.notice-sheet h1 {
  font-size: clamp(1.5rem, 3.4vw, 2.1rem);
  line-height: 1.2;
  margin-bottom: 12px;
}
.notice-loading {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.notice-page-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 22px;
}
.notice-back,
.notice-print {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blue);
}
.notice-back::before { content: "← "; }
.notice-print {
  min-height: 44px;
  padding: 10px 18px;
  border: 1px solid var(--blue);
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  transition: background 0.16s ease;
}
.notice-print:hover { background: var(--blue-wash); }
/* The notice band is tinted and runs to the footer, so the footer's usual
   breathing room would read as a stray white stripe under it. */
.footer-tight { margin-top: 0; }
.notice-sheet-meta {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 20px;
}
/* An opened notice has the page to itself, so nothing bounds the shape
   here except the screen: a poster shot upright would otherwise fill the
   sheet and push the notice itself out of sight. Capped, and shown whole
   rather than cropped. */
.notice-sheet-figure {
  /* a poster upright is narrower than the sheet once the cap bites, and
     centred it reads as pinned to the page rather than slid off it */
  margin: 0 auto 22px;
  aspect-ratio: var(--shot);
  max-height: 58vh;
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
  background: var(--blue-wash);
}
.notice-sheet-figure img {
  display: block;
  width: 100%;
  height: 100%;
  max-height: 58vh;
  object-fit: contain;
}
/* The rest of the run, under the words: the cover has already been
   printed above them. */
.notice-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px;
  margin-top: 26px;
}
.notice-gallery-figure {
  margin: 0;
  /* the same bargain as the board, a little tighter — these sit four to a
     row and a tall one drags the whole row down with it */
  aspect-ratio: clamp(0.7, var(--shot), 2.2);
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
  background: var(--blue-wash);
}
.notice-gallery-figure img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.notice-sheet-body p { max-width: 66ch; line-height: 1.75; }
.notice-sheet-body p + p { margin-top: 15px; }
.notice-sheet-by {
  margin-top: 26px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: 0.93rem;
}
.notice-sheet-by .by-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 3px;
}

/* The official letterhead: barangay seal left, the Republic's line-up in
   the middle, the city's seal right — set on a double rule, the way a
   printed order from the hall is headed. */
.notice-letterhead {
  display: grid;
  grid-template-columns: 56px 1fr 56px;
  align-items: center;
  gap: 16px;
  text-align: center;
  border-bottom: 4px double var(--ink);
  padding-bottom: 16px;
  margin-bottom: 24px;
}
.notice-letterhead .seal { width: 56px; height: 56px; display: block; }
.notice-letterhead .lh-line {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-soft);
  line-height: 1.7;
}
.notice-letterhead .lh-brgy {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
  letter-spacing: 0.01em;
  line-height: 1.25;
  color: var(--blue);
  margin: 3px 0;
}

/* ---------- Services ---------- */
.section-alt { background: var(--paper-deep); border-block: 1px solid var(--line); }

.svc-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
}
.svc-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: 0 1px 2px rgba(24, 34, 56, 0.05);
  transition: transform 0.14s ease, box-shadow 0.14s ease, border-color 0.14s ease;
}
.svc-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-paper);
  border-color: var(--blue);
}
.svc-card h3 { font-size: 1.22rem; }
.svc-meta {
  display: flex;
  gap: 14px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
}
.svc-meta .fee-free { color: var(--blue); font-weight: 600; }
.svc-card p { font-size: 0.92rem; color: var(--ink-soft); flex: 1; }
/* What to bring, on a walk-in service card. The description above keeps
   the flex slack, so these lists settle along the bottom of a row of
   cards instead of floating at different heights. */
.svc-card .card-reqs-title {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.card-reqs { list-style: none; display: flex; flex-direction: column; gap: 4px; }
.card-reqs li {
  font-size: 0.86rem;
  color: var(--ink-soft);
  padding-left: 19px;
  position: relative;
}
.card-reqs li::before {
  content: "□";
  position: absolute;
  left: 0;
  top: -1px;
  color: var(--blue);
}
.svc-link {
  color: var(--blue);
  font-weight: 700;
  font-size: 0.94rem;
  text-decoration: none;
}
.svc-link:hover { text-decoration: underline; }
.svc-more { margin-top: 28px; text-align: center; }

/* Services page — detail cards */
.svc-detail {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 1px 2px rgba(24, 34, 56, 0.05);
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  margin-bottom: 22px;
  overflow: hidden;
}
.svc-detail-main { padding: 28px; }
.svc-detail-main h3 { font-size: 1.45rem; margin-bottom: 6px; }
.svc-detail-main .svc-desc { color: var(--ink-soft); font-size: 0.97rem; margin-bottom: 16px; }
.req-title {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 8px;
}
.req-list { list-style: none; }
.req-list li {
  font-size: 0.93rem;
  padding: 4px 0 4px 26px;
  position: relative;
}
.req-list li::before {
  content: "□";
  position: absolute;
  left: 2px;
  top: 3px;
  color: var(--blue);
  font-size: 0.95rem;
}
.svc-detail-side {
  background: var(--blue-wash);
  border-left: 1px solid var(--line);
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.fact { line-height: 1.4; }
.fact dt {
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.fact dd {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.12rem;
}
.svc-detail-side .btn { margin-top: auto; }

/* ---------- How it works ---------- */
.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  counter-reset: step;
}
.step {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px;
  position: relative;
}
.step::before {
  counter-increment: step;
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--blue);
  display: inline-block;
  border: 1.5px solid var(--blue);
  background: var(--blue-wash);
  border-radius: 50%;
  width: 40px;
  height: 40px;
  line-height: 37px;
  text-align: center;
  margin-bottom: 14px;
}
.step h3 { font-size: 1.18rem; margin-bottom: 6px; }
.step p { font-size: 0.93rem; color: var(--ink-soft); }

/* ---------- Officials ----------

   Two columns, and the split is the barangay's own: everybody the
   barangay elected down the left, everybody it appointed or employs down
   the right. A resident looking for the Punong Barangay and a resident
   looking for the day care worker are asking different questions, and
   this is the one division that puts those two questions side by side
   instead of one under a scroll of the other.

   It was three full-width bands before, and the reason that was right
   then was arithmetic: seven faces do not fit a half page. Seven is now
   eight — the Sangguniang Kabataan Chairperson sits with the council ex
   officio — and eight is the number that makes the column work. Eight
   divides into whatever the column can hold: four and four, or three and
   three and two centred under them. Seven never did.

   The right column is a list of names, which is what a half page is the
   right width for in the first place. */

.off-section {
  display: grid;
  /* Wide enough on the left for four council squares abreast, which is
     what makes eight two whole rows; wide enough on the right for a
     roster to run two names abreast, which is what keeps twenty-one
     tanods off a scroll. Both of those are floors, and this is the
     narrowest split that clears them. */
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(30px, 3.4vw, 64px);
  align-items: start;
}
/* A barangay that has published one half of the section and not the
   other gets the width for the half it has, rather than a column of
   people beside an empty track. */
.off-section.is-one { grid-template-columns: minmax(0, 1fr); }
.off-col {
  display: flex;
  flex-direction: column;
  gap: clamp(30px, 3.4vw, 48px);
  min-width: 0;
}

.off-band-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue);
  padding-bottom: 9px;
  margin-bottom: clamp(16px, 2vw, 24px);
  border-bottom: 2px solid var(--blue);
}
/* Set by the renderer when a note follows, so the two read as one block
   rather than as a heading with a stray sentence under it. */
.off-band-head.has-note { margin-bottom: 10px; }
.off-band-note {
  margin-bottom: clamp(16px, 2vw, 24px);
  max-width: 62ch;
  font-size: 0.84rem;
  line-height: 1.5;
  color: var(--ink-soft);
}
.off-count {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--blue);
  background: var(--blue-wash);
  border-radius: 999px;
  padding: 2px 8px;
}

/* ----- the Punong Barangay -----

   The one band that is not a list, and the one surface in the section
   that is navy. The office is the heading above it, so the plate carries
   the name and nothing that repeats the name — which is why the name is
   set at several times the size of the ones on the council squares. The
   head of a barangay reads as the head of the column from the colour and
   the type, not from being the biggest square. */
.off-lead {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: clamp(18px, 2.2vw, 34px);
  background: var(--blue-deep);
  border-radius: var(--radius);
  padding: clamp(16px, 1.8vw, 26px);
  box-shadow: var(--shadow-paper);
}
.off-lead-photo {
  /* Sized against the column it is in rather than the page: this one is
     a shade over half the width of a council square beside it, which is
     the ratio that reads as "the head of this list" without the plate
     turning into a panel with a stamp on it. */
  /* Held above the size of a council square below it at every width the
     two columns are on. Which of the two faces is the head of the
     barangay is the one thing the top of this column has to say, and at
     19vw the plate and a seat came out the same size. */
  width: clamp(150px, 23vw, 330px);
  box-shadow: none;
  /* A shade off the panel behind it, so a square with no photograph in
     it yet is still a square rather than a hole. */
  background: #26355A;
  border: 1px solid rgba(169, 199, 238, 0.34);
}
/* The same block as the seats below, at the scale of the office. */
.off-lead-body {
  padding-top: clamp(12px, 1.4vw, 20px);
  border-top: 3px solid var(--sky);
}
.off-lead-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.5rem, 2.2vw, 2.6rem);
  line-height: 1.08;
  letter-spacing: -0.01em;
  color: var(--white);
  text-wrap: balance;
}
.off-lead-committee {
  margin-top: 10px;
  font-size: 0.94rem;
  line-height: 1.45;
  color: var(--sky);
}

/* ----- the Sangguniang Barangay -----

   Eight squares that wrap and centre: the seven kagawad elected at
   large, then the SK Chairperson, who sits with them ex officio and is
   drawn with them for that reason. The office written across each plate
   is what says which is which — an eighth square styled differently
   would be saying the SK Chairperson is a lesser member of the council,
   and they are not.

   Centred, so the row left over at the end sits under the one above it
   rather than against the left edge. A centred remainder reads as an
   arrangement; a remainder shoved left reads as a page that ran out. */
.off-council {
  --seat-gap: clamp(12px, 1.3vw, 20px);
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  /* Rows are set much further apart than columns, and further apart than
     a photograph is from its own caption. With the naming block sitting
     under the square, a row gap the size of the column gap leaves each
     block almost equidistant between the face it belongs to and the face
     below it — and at that point the eye picks the wrong one. */
  gap: clamp(28px, 2.6vw, 42px) var(--seat-gap);
}
/* Four across wherever the column can hold four legibly, because eight
   across four is two whole rows and the band comes out square. Three
   across below that — eight comes out three, three and two, and the two
   sit centred under the six.

   Three was the wrong answer on a desktop for a reason worth keeping:
   it made a council square as large as the Punong Barangay's photograph
   above it, and the one thing the top of this column has to say is which
   of the two is the head of the barangay. */
.off-seat {
  flex: 0 0 calc((100% - 3 * var(--seat-gap)) / 4);
  min-width: 0;
}
/* Below this, four across puts a council square under 175px, which is
   where a name, an office and a committee stop fitting on one. */
@media (max-width: 1400px) {
  .off-seat { flex-basis: calc((100% - 2 * var(--seat-gap)) / 3); }
}

/* ----- the portrait -----

   Square, because the photograph a barangay has of an official is a 1x1
   ID photograph and cropping it to anything else takes a shoulder off.
   Not a circle for the same reason, only more so.

   The corner is the document corner the rest of the site uses. It was a
   26% squircle while the name was printed across the foot of the
   photograph — a soft corner suits a caption floating on an image. It
   does not suit a public register: at the size these are drawn, 26%
   reads as an app icon, and an official portrait in a record has the
   corner a printed record has. It also lets the rule below sit flush to
   the photograph's own edges, so the naming block reads as built on the
   portrait rather than floating under a curve. */
.off-portrait {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--blue-deep);
  display: grid;
  place-items: center;
  box-shadow: var(--shadow-paper);
}
.off-photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* No photograph yet. Initials rather than a silhouette — a grey outline
   of a person reads as something broken, and initials read as somebody
   whose picture has not been taken. Centred, now that nothing is printed
   over the foot of the square. */
.off-initials {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.4rem;
  letter-spacing: 0.02em;
  color: var(--sky);
}
@supports (container-type: inline-size) {
  .off-portrait { container-type: inline-size; }
  .off-initials { font-size: 22cqw; }
}

/* The name, the office and the committee across the foot of the
   photograph rather than under it — which keeps a row of squares even
   when one caption runs to two lines and its neighbour does not. */
/* ----- the block that names a portrait -----

   A rule, then the name, then the office and the committee under it —
   set on the page beneath the photograph rather than printed across it.

   **The rule is above the name, not below.** That is where a barangay
   puts it: every document the hall issues ends with a name set under a
   rule with the office beneath, and these are the people who sign them.
   It is the section's one borrowed gesture and it earns its place twice,
   because every photograph is square — so the rule lands on the same
   line right across a row however many lines the name above it ran to,
   and a caption that wraps can no longer knock the grid out of true.

   What this replaced was the name, the office and the committee printed
   across the foot of the photograph behind a dark gradient. Over
   initials on navy that is even and legible. Over forty-three real
   photographs it is a lottery — every one of them has its own brightness
   where the text lands — and it spends the bottom half of an official
   portrait, which is the half with the shoulders in it, on a scrim.
   Off the photograph, the contrast is the same on every card and is a
   fact rather than a hope. */
.off-card {
  display: flex;
  flex-direction: column;
}
.off-plate {
  margin-top: clamp(9px, 0.9vw, 12px);
  padding-top: 9px;
  border-top: 3px solid var(--blue);
  display: flex;
  flex-direction: column;
}
.off-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.22;
  color: var(--ink);
  text-wrap: balance;
}
/* The office, and only where the band overhead has not already said it.
   Seven squares each repeating "Barangay Kagawad" under a heading that
   reads "Sangguniang Barangay" is ink spent on nothing — and leaving it
   off is what lets the one office that is news, the SK Chairperson
   sitting ex officio, read as news. */
.off-role {
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--blue);
  line-height: 1.35;
}
/* On a council of seven who all hold the same office, the committee is
   the whole of what tells them apart — it is what a resident is reading
   the square to find. */
.off-committee {
  margin-top: 4px;
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--ink-soft);
}

/* ----- everybody else -----

   A title, then the names under it, ruled off from the group above and
   below. The names run in as many columns as the width will take, so one
   secretary and twenty-one tanods come out the same shape — which is the
   reason this is a ruled list and not a grid of cards: a card sized for
   twenty-one names is a very empty card with one name in it.

   The title sits over its roster rather than beside it. Beside it is the
   better reading when the section has a whole page; in a column it costs
   the roster the width that lets it run two names abreast, and a list of
   twenty-one single-file names is a scroll. */
.off-groups { border-top: 1px solid var(--line); }
.off-group {
  padding: 15px 0 17px;
  border-bottom: 1px solid var(--line);
}
.off-group-head { margin-bottom: 8px; }
.off-group-title {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  line-height: 1.25;
  color: var(--ink);
}
.off-group-note {
  margin-top: 4px;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--ink-soft);
}

/* Column width rather than a column count, so the roster finds its own
   number of columns in whatever width the column turns out to be — and a
   group of one gets one column instead of a name stretched across the
   page. */
.off-roster {
  list-style: none;
  /* Wide enough for the longest line in the roster — a name over an
     office in small caps — and no wider, because every 10px added here
     is a width at which the column drops from two abreast to one and
     the roster doubles in height. */
  columns: 176px;
  column-gap: 26px;
}
.off-roster li {
  break-inside: avoid;
  padding: 3px 0;
}
.off-rname {
  display: block;
  font-size: 0.9rem;
  line-height: 1.35;
  color: var(--ink);
}
.off-rrole {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.57rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: 1px;
}

/* A group that draws faces. Sized rather than stretched: one face in a
   group is one square the size of the others, not one square the width
   of the column. */
.off-faces {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 26px 12px;
}
.off-face { flex: 0 0 clamp(124px, 11vw, 172px); }
/* A group's square is smaller than a council seat's, so its block is set
   a step down to keep the same relation to the photograph above it. */
.off-face .off-plate { padding-top: 7px; border-top-width: 2px; }
.off-face .off-name { font-size: 0.83rem; }
.off-face .off-role { font-size: 0.5rem; letter-spacing: 0.09em; margin-top: 3px; }
.off-face .off-committee { font-size: 0.72rem; margin-top: 3px; }

.off-empty {
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.officials-note {
  margin-top: 26px;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

/* ----- narrower -----

   Below this the two columns are two columns of nothing much: the
   council squares go under 175px and the right-hand roster drops to a
   single file of names, which is the point at which side by side costs
   more height than it saves. One under the other instead, elected first
   — the order they are in when the columns are side by side, read the
   way a page is read. */
@media (max-width: 1120px) {
  .off-section {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(30px, 4vw, 48px);
  }
  /* The council has the whole page back, so it takes the width. */
  .off-seat { flex-basis: calc((100% - 3 * var(--seat-gap)) / 4); }
  .off-lead-photo { width: clamp(190px, 30vw, 380px); }
  .off-lead-name { font-size: clamp(1.7rem, 4.6vw, 3.1rem); }
  .off-lead-committee { font-size: 1rem; }
  .off-face { flex: 0 0 clamp(140px, 16vw, 200px); }
}

@media (max-width: 820px) {
  .off-seat { flex-basis: calc((100% - 2 * var(--seat-gap)) / 3); }
}

@media (max-width: 760px) {
  .off-lead {
    grid-template-columns: minmax(0, 1fr);
    gap: 18px;
  }
}

@media (max-width: 560px) {
  .off-seat { flex-basis: calc((100% - var(--seat-gap)) / 2); }
  /* The block is page type, not something written on the photograph, so
     it keeps its size while the square changes — only the name comes
     down, because two across on a phone is a column about 160px wide and
     a name has to fit it. */
  .off-name { font-size: 0.86rem; }
}

@media print {
  /* Paper has one column and the two here are not worth the guttering. */
  .off-section { display: block; }
  .off-col + .off-col { margin-top: 26px; }
  .off-lead { box-shadow: none; }
  .off-band, .off-group, .off-seat { break-inside: avoid; }
  .off-council { justify-content: flex-start; }
}

/* ---------- Visit ---------- */
.visit-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 32px;
  align-items: start;
}
.visit-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 28px;
}
.visit-card h3 { font-size: 1.25rem; margin-bottom: 12px; }
.hours-table { width: 100%; border-collapse: collapse; font-size: 0.94rem; }
.hours-table td { padding: 8px 0; border-bottom: 1px dashed var(--line); }
.hours-table td:last-child { text-align: right; font-family: var(--font-mono); font-size: 0.8rem; }
.hotline-list { list-style: none; }
.hotline-list li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px dashed var(--line);
  font-size: 0.94rem;
}
.hotline-list .num { font-family: var(--font-mono); font-size: 0.8rem; white-space: nowrap; }
.visit-note { margin-top: 14px; font-size: 0.85rem; color: var(--ink-soft); }

/* ---------- Page hero (inner pages) ---------- */
.page-hero {
  background: var(--paper-deep);
  border-bottom: 1px solid var(--line);
  padding-block: 48px;
}
.breadcrumb {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 14px;
}
.breadcrumb a { color: var(--ink-soft); }
.page-hero h1 { font-size: clamp(2rem, 4.5vw, 3rem); font-weight: 700; }
.page-hero .lede { margin-top: 10px; max-width: 60ch; color: var(--ink-soft); }

/* ---------- FAQ ---------- */
.faq { max-width: 780px; }
.faq details {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-bottom: 12px;
}
.faq summary {
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.08rem;
  padding: 18px 22px;
  list-style: none;
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  position: absolute;
  right: 20px;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-mono);
  color: var(--blue);
  font-size: 1.2rem;
  transition: transform 0.25s ease;
}
/* the plus turns into a close mark instead of swapping glyphs */
.faq details[open] summary::after { transform: translateY(-50%) rotate(45deg); }
.faq details p {
  padding: 0 22px 18px;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

/* ---------- Request form ---------- */
.form-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  gap: 32px;
  align-items: start;
}
.form-sheet {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 2px;
  box-shadow: var(--shadow-paper);
  padding: 36px 40px 40px;
}
.form-sheet-head {
  display: flex;
  align-items: center;
  gap: 14px;
  border-bottom: 2px solid var(--ink);
  padding-bottom: 16px;
  margin-bottom: 28px;
}
.form-sheet-head .seal { width: 46px; height: 46px; flex: none; }
.form-no {
  margin-left: auto;
  white-space: nowrap;
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-align: right;
  line-height: 1.7;
}
.form-sheet-head .lh-line {
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  line-height: 1.6;
}
.form-sheet-head .lh-brgy {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--blue);
}

fieldset {
  border: none;
  margin-bottom: 30px;
}
legend {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
  margin-bottom: 4px;
}
.legend-note { font-size: 0.86rem; color: var(--ink-soft); margin-bottom: 16px; }

.field-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 18px;
}
.field { display: flex; flex-direction: column; gap: 5px; }
.field.full { grid-column: 1 / -1; }
.field label {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.field label .req-mark { color: var(--blue); }
.field input,
.field select,
.field textarea {
  width: 100%;
  min-width: 0;
  font-family: var(--font-body);
  /* 16px is the floor: below it iOS zooms the page in when the field takes
     focus and never zooms back out */
  font-size: 1rem;
  color: var(--ink);
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: 4px;
  padding: 11px 12px;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(33, 82, 148, 0.18);
}
.field .hint { font-size: 0.78rem; color: var(--ink-soft); }
/* What you attached, shown back to you before you commit to it */
.upload-preview {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 4px;
}
.upload-preview img {
  width: 96px;
  height: 72px;
  object-fit: cover;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--blue-wash);
}
.upload-preview img[hidden] { display: none; }
.upload-clear {
  appearance: none;
  background: none;
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 6px 12px;
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
}
.upload-clear:hover { border-color: var(--blue); color: var(--blue-dark); }
.radio-row { display: flex; flex-wrap: wrap; gap: 10px; }
.radio-pill {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1.5px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 16px;
  font-size: 0.94rem;
  cursor: pointer;
}
.radio-pill:has(input:checked) {
  border-color: var(--blue);
  background: var(--blue-wash);
  font-weight: 600;
}
.radio-pill input { accent-color: var(--blue); }
.check-row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 0.92rem;
  color: var(--ink-soft);
}
.check-row input { margin-top: 4px; accent-color: var(--blue); }
.form-actions {
  border-top: 1px dashed var(--line);
  padding-top: 24px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.form-actions .small-print { font-size: 0.8rem; color: var(--ink-soft); }
.recaptcha-field { flex-basis: 100%; }
.form-error {
  flex-basis: 100%;
  font-size: 0.9rem;
  font-weight: 600;
  color: #A23B3B;
}

/* Sidebar on request page */
.aside-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
  margin-bottom: 20px;
}
.aside-card h3 { font-size: 1.1rem; margin-bottom: 10px; }
.aside-card ul { padding-left: 20px; font-size: 0.9rem; color: var(--ink-soft); }
/* The line under a card heading that explains what the field below wants. */
.aside-hint { font-size: 0.9rem; color: var(--ink-soft); }
.aside-card li { margin-bottom: 6px; }
.aside-card .track-field { display: flex; gap: 8px; margin-top: 12px; }
.aside-card .track-field input {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  border: 1.5px solid var(--line);
  border-radius: 4px;
  padding: 10px 12px;
  text-transform: uppercase;
}
.aside-card .track-field input:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(33, 82, 148, 0.18);
}
.track-result { margin-top: 14px; font-size: 0.9rem; }
.track-result .status-line {
  display: flex;
  gap: 10px;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px dashed var(--line);
}
.track-result .status-line .dot {
  width: 10px;
  height: 10px;
  flex: none;
  border-radius: 50%;
  background: var(--blue);
  align-self: center;
}
.track-result .mono { font-family: var(--font-mono); font-size: 0.76rem; color: var(--ink-soft); }

/* Confirmation */
.confirm-panel {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 2px;
  box-shadow: var(--shadow-paper);
  padding: 48px 40px;
  text-align: center;
  position: relative;
}
.confirm-panel .stamp-big {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 1.3rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--blue);
  border: 4px double var(--blue);
  border-radius: 6px;
  padding: 12px 28px;
  display: inline-block;
  margin-bottom: 26px;
}
/* Set square. This is the receipt a resident screenshots and brings back
   to the hall, so it should read as an official mark rather than a
   sticker; the stamp still lands with a thunk, it just lands straight. */
.confirm-panel.stamped .stamp-big { animation: stamp-thunk 0.45s cubic-bezier(0.2, 1.6, 0.4, 1) both; }
@keyframes stamp-thunk {
  0% { transform: scale(2.6); opacity: 0; }
  60% { transform: scale(0.94); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
.confirm-panel h2 { font-size: 1.7rem; margin-bottom: 8px; }
.confirm-panel .ref-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: 22px;
}
.confirm-panel .ref-no {
  font-family: var(--font-mono);
  /* the number is the one thing on this screen the resident has to copy
     down, so it scales with the viewport rather than breaking across
     three lines on a phone */
  font-size: clamp(0.95rem, 4.4vw, 1.5rem);
  white-space: nowrap;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--blue);
  background: var(--blue-wash);
  border: 1.5px dashed var(--blue);
  border-radius: var(--radius);
  display: inline-block;
  padding: 10px 24px;
  margin: 8px 0 22px;
}
.confirm-panel .next-steps {
  text-align: left;
  max-width: 460px;
  margin: 0 auto 26px;
  font-size: 0.94rem;
  color: var(--ink-soft);
}
.confirm-panel .next-steps li { margin-bottom: 8px; }
.confirm-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

[hidden] { display: none !important; }

/* ---------- Error page (404 etc.) ---------- */
.error-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 58vh;
  padding-block: 64px;
}
.error-card {
  width: 100%;
  max-width: 520px;
  margin-inline: auto;
  text-align: center;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 2px;
  box-shadow: var(--shadow-paper);
  padding: 52px 44px 44px;
}
.error-card .seal { width: 64px; height: 64px; margin: 0 auto 16px; display: block; }
.error-card .brand-lines { display: block; }
.error-card .brand-lines .republic { display: block; font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-soft); }
.error-card .brand-lines .bname { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.2rem; color: var(--ink); margin-top: 2px; }
.error-card .brand-lines .locality { display: block; font-size: 0.8rem; color: var(--ink-soft); margin-top: 1px; }
.error-card .stamp-big {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 1.5rem;
  letter-spacing: 0.18em;
  color: var(--blue);
  border: 4px double var(--blue);
  border-radius: 6px;
  padding: 10px 26px;
  display: inline-block;
  margin: 26px 0 22px;
  transform: rotate(-4deg);
}
.error-card h1 { font-size: clamp(1.4rem, 4vw, 1.7rem); margin-bottom: 12px; }
.error-card p { color: var(--ink-soft); font-size: 0.96rem; max-width: 40ch; margin-inline: auto; }
.error-card .error-path {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--ink-soft);
  background: var(--blue-wash);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 8px 14px;
  margin: 18px auto 0;
  display: inline-block;
  word-break: break-all;
}
.error-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 30px; }
.error-card .small-print { margin-top: 22px; font-size: 0.8rem; color: var(--ink-soft); }
.error-card .small-print a { color: var(--blue); }

@media (max-width: 620px) {
  .error-card { padding: 40px 24px 34px; }
  .error-card .stamp-big { font-size: 1.15rem; padding: 8px 18px; }
}

/* ---------- Legal documents (privacy notice, terms of use) ----------
   Set as an issuance, not a web page: a control block at the head, numbered
   sections you can cite by number, and a standing index down the side. */
/* Three tracks, centred as a block: the index down the left, the document
   itself held at a readable measure, and the reference apparatus down the
   right. The measure is what a legal document is read at, so the page is
   not widened to fill the screen — the margins are given work instead. */
.legal-layout {
  display: grid;
  grid-template-columns: minmax(0, 224px) minmax(0, 74ch) minmax(0, 292px);
  justify-content: center;
  gap: 56px;
  align-items: start;
}
.legal-toc {
  position: sticky;
  top: 116px;
  border-left: 2px solid var(--line);
  padding-left: 18px;
}
/* the section being read is marked in the index as you scroll */
.legal-toc a[aria-current="true"] {
  color: var(--blue-dark);
  font-weight: 600;
}
.legal-toc a[aria-current="true"]::before { color: var(--blue-dark); }
.legal-toc h2 {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 12px;
}
.legal-toc ol { list-style: none; counter-reset: toc; }
.legal-toc li { counter-increment: toc; margin-bottom: 7px; }
.legal-toc a {
  display: block;
  font-size: 0.86rem;
  line-height: 1.4;
  color: var(--ink-soft);
  text-decoration: none;
}
.legal-toc a::before {
  content: counter(toc) ".";
  font-family: var(--font-mono);
  font-size: 0.74rem;
  color: var(--blue);
  margin-right: 7px;
}
.legal-toc a:hover { color: var(--blue); }

.legal-doc { max-width: 74ch; }
.legal-meta {
  background: var(--blue-wash);
  border: 1px solid var(--line);
  border-left: 4px solid var(--blue);
  border-radius: var(--radius);
  padding: 20px 24px;
  margin-bottom: 44px;
  font-size: 0.9rem;
}
.legal-meta > div {
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr);
  gap: 4px 16px;
  padding: 6px 0;
  border-bottom: 1px dashed var(--line);
}
.legal-meta > div:last-child { border-bottom: none; }
.legal-meta dt {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding-top: 3px;
}
.legal-meta dd { color: var(--ink); }

.legal-doc > section { margin-bottom: 40px; scroll-margin-top: 120px; }
.legal-doc h2 {
  font-size: 1.32rem;
  font-weight: 700;
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}
.legal-no {
  font-family: var(--font-mono);
  font-size: 0.74em;
  font-weight: 600;
  color: var(--blue);
  margin-right: 10px;
}
.legal-doc h3 {
  font-size: 1.02rem;
  font-weight: 600;
  margin: 22px 0 8px;
}
.legal-doc p,
.legal-doc li { color: var(--ink-soft); font-size: 0.97rem; }
.legal-doc p + p { margin-top: 12px; }
.legal-doc ul,
.legal-doc ol { padding-left: 22px; margin-top: 10px; }
.legal-doc li { margin-bottom: 8px; }
.legal-doc li > strong { color: var(--ink); }
.legal-doc a { color: var(--blue); overflow-wrap: anywhere; }
.legal-doc table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 14px;
  font-size: 0.92rem;
}
.legal-doc th,
.legal-doc td {
  text-align: left;
  vertical-align: top;
  padding: 10px 12px;
  border: 1px solid var(--line);
  color: var(--ink-soft);
}
.legal-doc th {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--blue-wash);
  font-weight: 600;
}
/* statute in the margin of the paragraph it governs */
.legal-cite {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  border-left: 2px solid var(--line);
  padding-left: 12px;
  margin-top: 12px;
}
.legal-callout {
  background: var(--white);
  border: 1px solid var(--line);
  border-top: 4px solid var(--blue);
  border-radius: var(--radius);
  padding: 22px 24px;
  margin-top: 18px;
  box-shadow: var(--shadow-paper);
}
.legal-callout h3 { margin-top: 0; }
.legal-callout p { font-size: 0.94rem; }
/* fields the barangay has to fill in before this is published */
.legal-fill {
  font-family: var(--font-mono);
  font-size: 0.86em;
  color: var(--blue-dark);
  background: var(--blue-wash);
  border-bottom: 1px dashed var(--blue);
  padding: 1px 5px;
}
/* ----- The right margin: what a reader needs beside the text, not more text.
   The statutes the page is built on, the documents it sits with, and a way
   to take a copy away. ----- */
.legal-aside {
  position: sticky;
  top: 116px;
  display: grid;
  gap: 18px;
  /* the terms page cites enough statutes to outgrow a laptop screen; bound
     the rail so it stays put instead of scrolling away and never coming back */
  max-height: calc(100vh - 140px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
  padding-right: 2px;
}
.rail-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px 20px 20px;
}
.rail-card h2 {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding-bottom: 10px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.rail-card p { font-size: 0.88rem; color: var(--ink-soft); }
.rail-card ul { list-style: none; }

/* every act this page actually rests on, in one place */
.rail-statutes li { margin-bottom: 11px; font-size: 0.86rem; line-height: 1.45; }
.rail-statutes li:last-child { margin-bottom: 0; }
.rail-statutes b {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--blue);
}
.rail-statutes span { color: var(--ink-soft); }

.rail-links li { margin-bottom: 2px; }
.rail-links a {
  display: flex;
  align-items: baseline;
  gap: 9px;
  padding: 8px 0;
  font-size: 0.89rem;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px dashed var(--line);
}
.rail-links li:last-child a { border-bottom: none; }
.rail-links a::before {
  content: "→";
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--blue);
  transition: transform 180ms ease;
}
.rail-links a:hover { color: var(--blue); }
.rail-links a:hover::before { transform: translateX(3px); }

.rail-print {
  width: 100%;
  margin-top: 12px;
  font-family: var(--font-body);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--blue-dark);
  background: var(--blue-wash);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 14px;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease;
}
.rail-print:hover { background: var(--white); border-color: var(--blue); }

.legal-doc .updated {
  margin-top: 44px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
}

@media (max-width: 1240px) {
  /* not enough room for three tracks: the reference cards come out of the
     margin and sit under the document as a row */
  .legal-layout { grid-template-columns: minmax(0, 224px) minmax(0, 74ch); gap: 48px; }
  .legal-aside {
    grid-column: 2;
    position: static;
    grid-template-columns: repeat(auto-fit, minmax(228px, 1fr));
    gap: 18px;
    padding-top: 8px;
    max-height: none;
    overflow: visible;
  }
}
@media (max-width: 960px) {
  /* the index stops being a margin and becomes a header for the document */
  .legal-layout { grid-template-columns: minmax(0, 1fr); }
  .legal-toc {
    position: static;
    border-left: none;
    border-bottom: 1px solid var(--line);
    padding-left: 0;
    padding-bottom: 24px;
  }
  .legal-toc ol { columns: 2; column-gap: 28px; }
  .legal-toc li { break-inside: avoid; }
  .legal-aside { grid-column: 1; }
}
@media (max-width: 620px) {
  .legal-layout { gap: 32px; }
  .legal-toc ol { columns: 1; }
  .legal-meta { padding: 16px 18px; }
  .legal-meta > div { grid-template-columns: minmax(0, 1fr); }
  .legal-doc h2 { font-size: 1.18rem; }
  /* a bordered table cannot narrow past its own columns; let it carry its
     own scroller rather than widening the page */
  .legal-scroll { overflow-x: auto; }
}

/* A printed copy of an issuance is the document, not the website around it. */
@media print {
  .govbar, .flag-stripe, .masthead, .footer, .skip-link,
  .legal-toc, .legal-aside, .page-hero .breadcrumb,
  .notice-page .breadcrumb, .notice-page-foot { display: none !important; }
  body { background: #fff; font-size: 11pt; }
  /* A notice printed off this page is the notice as posted at the hall: the
     letterhead and the seals stay, the furniture around them goes. */
  .notice-page { background: #fff; border: 0; padding: 0; }
  .notice-page .wrap > * { max-width: none; }
  .notice-sheet { border: 0; box-shadow: none; padding: 0; }
  .notice-sheet-figure { break-inside: avoid; }
  .notice-letterhead { break-after: avoid; }
  .legal-layout { display: block; }
  .legal-doc { max-width: none; }
  .legal-doc > section { break-inside: avoid; margin-bottom: 22px; }
  .legal-doc h2, .legal-doc h3 { break-after: avoid; }
  .legal-callout, .legal-meta { box-shadow: none; break-inside: avoid; }
  .legal-doc a { color: inherit; text-decoration: underline; }
}

/* ---------- Footer ---------- */
.footer {
  background: var(--blue-deep);
  color: #B9C7E6;
  margin-top: 72px;
}
.footer .wrap { padding-block: 52px 28px; }
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: 36px;
  padding-bottom: 36px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}
/* Both seals the barangay answers to: its own, and the city's. They sit as
   a pair rather than stacked, the way they would on a document header. */
.footer-seals { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
.footer-seal { width: 66px; height: 66px; flex: none; }
.footer .brand-lines .republic { color: #8FA5D4; }
.footer .brand-lines .bname { color: #fff; font-size: 1.3rem; }
.footer .brand-lines .locality { color: #8FA5D4; }
.footer-tagline {
  margin-top: 14px;
  font-family: var(--font-display);
  font-style: italic;
  color: var(--sky);
  font-size: 1.02rem;
}
.footer h4 {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #8FA5D4;
  margin-bottom: 14px;
}
.footer ul { list-style: none; }
.footer li { margin-bottom: 9px; }
.footer a { color: #D5DEF2; text-decoration: none; font-size: 0.92rem; overflow-wrap: anywhere; }
.footer a:hover { color: #fff; }
/* Three things of very different weight: the copyright, the motto, and the
   two legal links. Stacked and centred on a phone; on a wide screen a
   1fr–auto–1fr grid, which centres the motto against the rule itself
   rather than against whichever neighbour happens to be longer. */
.footer-bottom {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 14px;
  padding-top: 22px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: #8FA5D4;
}
/* Not before 1180px: the side columns are equal, so the motto only lands
   on the true centre once the longer of the two — the copyright line —
   has a column it fits on one line. */
@media (min-width: 1180px) {
  .footer-bottom {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: 24px;
    justify-items: start;
    text-align: left;
  }
  .footer-bottom > :last-child { justify-self: end; }
}
/* The hall's own words, set the way they are painted on the wall rather
   than in the mono of the legal strip around them. Parisienne is a
   moderate-contrast script on purpose: the engraved faces put their
   upstrokes on hairlines, and a hairline on navy at this size is a gap. */
.footer-motto {
  font-family: var(--font-script);
  font-size: 1.5rem;
  line-height: 1.15;
  letter-spacing: 0;
  color: #F0F5FD;
  /* Script faces sit high in the em box; the lead-in and exit strokes need
     the room, and the optical centre is a shade above the metric one. */
  padding-block: 2px;
}
/* Privacy and terms sit in the bottom rule rather than in a column, so they
   survive the phone layout, where the link columns step out. */
.footer-legal { display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center; justify-content: center; }
.footer-legal a { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; }
.footer-legal a[aria-current="page"] { color: #fff; }

/* ---------- Cookies and browser storage ----------
   Built by js/main.js, so it appears on no page that has already been
   answered.

   Not the dark rounded bar every site wears. This one is set as what it
   actually is: a short extract from the barangay's own privacy notice,
   in the notice's own clothes — the blue rule the legal callouts carry,
   the mono eyebrow, and the statute cited in the margin underneath.

   This is its narrow shape — a slip laid on the corner of the desk,
   where the page behind it stays readable and usable, because somebody
   who came for the office hours should get the office hours. On a screen
   with room it stands across the door instead; see the min-width block
   below, and openConsent() in js/main.js, which changes what it *is* at
   the same width. */
.consent {
  position: fixed;
  left: var(--gutter);
  bottom: var(--gutter);
  z-index: 90;
  max-width: 440px;
}
.consent-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-top: 4px solid var(--blue);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
  padding: 20px 22px 18px;
}
.consent-card .eyebrow { margin-bottom: 10px; }
.consent-card h2 { font-size: 1.15rem; margin-bottom: 10px; }
.consent-card p { font-size: 0.87rem; line-height: 1.55; color: var(--ink-soft); }
.consent-card p + p { margin-top: 8px; }
/* The line that is actually advice rather than disclosure. It earns the
   ink colour the rest of the copy gives up. */
.consent-aside {
  margin-top: 12px !important;
  border-left: 2px solid var(--blue-wash);
  padding-left: 12px;
  color: var(--ink) !important;
}
.consent-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
/* Neither answer is the small print of the other: both are full-size
   targets, and refusing takes exactly as many taps as allowing. */
.consent-actions .btn { flex: 1 1 auto; padding: 11px 18px; font-size: 0.9rem; }
.consent-card .legal-cite { margin-top: 14px; font-size: 0.68rem; }
.consent-card .legal-cite a { color: var(--blue); }

/* ---------- On a screen with room, it is a gate after all ----------
   A slip on the corner of the desk is the right shape for a phone, where
   the notice already takes the whole width and a reader thumbs past it in
   a second. On a monitor the same card sits in one corner of a very large
   page and is easy to read as somebody else's business — and this is the
   one thing on the site a person is asked to answer before anything else
   is done on their behalf. So here it stands across the door: the page
   dimmed behind it, the notice in the middle at a size meant to be read.

   Its looks and its behaviour change together — main.js makes it a real
   dialog at this width, moves the cursor into it, keeps Tab inside it and
   gives Escape the same answer as the button that keeps least. A card
   that only looks like a gate would be worse than either shape.

   621px is not a new number: it is the far side of the one breakpoint
   this notice already had. */
@media (min-width: 621px) {
  .consent {
    inset: 0;
    max-width: none;
    /* over the letterhead, under the skip link */
    z-index: 150;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--gutter);
    background: rgba(24, 35, 63, 0.58);
    overflow-y: auto;
  }
  .consent-card {
    width: 100%;
    max-width: 560px;
    /* a short window scrolls the notice, never clips it: the sentence
       about a shared computer is at the bottom of it */
    max-height: calc(100vh - var(--gutter) * 2);
    max-height: calc(100dvh - var(--gutter) * 2);
    overflow-y: auto;
    padding: 32px 36px 28px;
  }
  .consent-card h2 { font-size: 1.5rem; margin-bottom: 12px; }
  .consent-card p { font-size: 0.95rem; line-height: 1.65; }
  .consent-card p + p { margin-top: 11px; }
  .consent-actions { margin-top: 22px; }
  .consent-actions .btn { padding: 13px 22px; font-size: 0.95rem; }
  .consent-card .legal-cite { margin-top: 18px; }
}
/* The page dims; the notice rises into it. */
@media (min-width: 621px) and (prefers-reduced-motion: no-preference) {
  .consent { animation: consent-scrim 0.22s ease-out both; }
}
@keyframes consent-scrim {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* The way back, in the rule at the foot of every page beside the two
   documents it belongs with. */
.footer-legal button {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.footer-legal button:hover { color: #fff; }

/* Rises once, from where the desk edge would be. */
@media (prefers-reduced-motion: no-preference) {
  .consent-card { animation: consent-in 0.32s ease-out both; }
}
@keyframes consent-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

/* Google's check, waiting to be asked. Dashed, because it is a space
   held open for something that is not there yet — the same reading the
   empty seal gets. */
.captcha-ask {
  /* --sky rather than --line: a dash the same value as the fill behind
     it is a solid edge, and the whole point of the dash is that this is
     a space being held open rather than a panel. */
  border: 1px dashed var(--sky);
  border-radius: var(--radius);
  background: var(--blue-wash);
  padding: 14px 16px;
}
.captcha-ask p { font-size: 0.85rem; line-height: 1.5; color: var(--ink); margin-bottom: 10px; }
.captcha-ask .btn { padding: 9px 16px; font-size: 0.88rem; background: var(--white); }

/* ---------- Reveal on scroll ----------
   js/main.js staggers siblings that enter together, then strips the class
   once the transition ends so card hover transitions take back over. */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.reveal.in { opacity: 1; transform: none; }

/* ---------- Page-load entrance ----------
   The banner content rises as the page opens: heading column first, then
   the certificate (home) or the lede (inner pages). Transform and opacity
   only, so nothing shifts layout. */
@media (prefers-reduced-motion: no-preference) {
  .hero .wrap > *,
  .page-hero .wrap > * {
    animation: rise-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) backwards;
  }
  .hero .wrap > :nth-child(2),
  .page-hero .wrap > :nth-child(2) { animation-delay: 0.1s; }
  .page-hero .wrap > :nth-child(3) { animation-delay: 0.18s; }
}
@keyframes rise-in {
  from { opacity: 0; transform: translateY(16px); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .confirm-panel.stamped .stamp-big { animation: none; }
  .btn, .svc-card, .cert-paper, .cert-folder, .faq summary::after { transition: none; }
  .cert-stage:hover { --cert-lift: 0px; }
  .notice-card, .notice-open, .notice-print { transition: none; }
  .notice-card:hover { transform: none; }
}

/* ---------- Wide screens ----------
   The container is full-bleed, so the job here is to spend the extra width on
   more content per row rather than on wider cards and longer lines. Prose
   blocks keep their own measure caps (.section-head, .lede, .step p). */
@media (min-width: 1000px) {
  /* two columns of questions rather than one narrow column beside a void */
  .faq { max-width: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 16px; align-items: start; }
}

@media (min-width: 1200px) {
  :root { --gutter: 48px; }
  /* Track count follows the space available: at 240px a card still fits its
     longest role ("Kagawad · Infrastructure") beside the avatar. */
}

@media (min-width: 1440px) {
  /* still inside the 60-75 char measure, but it no longer leaves the hero
     column half empty */
  .hero .lede { max-width: 58ch; }
}

@media (min-width: 1600px) {
  :root { --gutter: 72px; }
  /* give the sidebar more of the sheet's width so inputs stay a usable size */
  .form-layout { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
  /* scale the whole certificate rather than resizing its parts, so the
     letterhead type keeps the fit it was set for */
  .cert-stage { min-height: 650px; --cert-scale: 1.18; }
}

@media (min-width: 1920px) {
  :root { --gutter: 104px; }
}

/* ---------- Responsive ---------- */
/* minmax(0, 1fr) rather than 1fr throughout: a bare 1fr track refuses to
   shrink below its content's min-content width, which on a narrow phone
   pushes the whole page wider than the screen. */
@media (max-width: 960px) {
  .hero .wrap { grid-template-columns: minmax(0, 1fr); gap: 48px; padding-block: 60px; }
  .cert-stage { min-height: 500px; }
  .visit-grid,
  .form-layout { grid-template-columns: minmax(0, 1fr); }
  .svc-grid, .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .svc-detail { grid-template-columns: minmax(0, 1fr); }
  .svc-detail-side { border-left: none; border-top: 1px solid var(--line); }
  /* four footer columns at tablet width leave each one too narrow for a
     service name to sit on a single line */
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px; }
}

/* Two seals plus the full nav need ~1040px of letterhead; below that the
   nav folds into the menu button so the seals keep their corners. */
@media (max-width: 1040px) {
  .nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--white);
    border-bottom: 1px solid var(--line);
    flex-direction: column;
    align-items: stretch;
    padding: 12px 24px 20px;
    gap: 6px;
    z-index: 100;
    box-shadow: 0 16px 32px rgba(24, 34, 56, 0.12);
  }
  .nav.open { display: flex; }
  .nav a:not(.btn) { padding: 12px 14px; }
  .nav a.active { box-shadow: inset 4px 0 0 var(--blue); }
  .nav .btn { margin-left: 0; margin-top: 8px; }
  .nav-toggle { display: block; }
  /* the masthead is sticky, which already anchors the dropdown nav */
}

@media (max-width: 620px) {
  /* A phone has no desk corner to lay a slip on. The notice takes the
     foot of the screen instead, and loses the rounded bottom so it
     reads as part of the edge rather than as a card floating on it.
     The two answers go full width and stack, which keeps both of them
     at a comfortable tap size — the size is the choice. */
  .consent { left: 0; right: 0; bottom: 0; max-width: none; }
  .consent-card {
    border-left: 0;
    border-right: 0;
    border-bottom: 0;
    border-radius: 0;
    padding: 18px var(--gutter) 16px;
    max-height: 84vh;
    overflow-y: auto;
  }
  /* A full 16px on a phone. This is the one thing on the site somebody
     is asked to agree to before they have read anything else, and
     shrinking it to save the screen room would be saving room in the
     wrong place. */
  .consent-card p { font-size: 1rem; }
  .consent-actions .btn { flex: 1 1 100%; padding: 13px 18px; }

  .section { padding-block: 52px; }
  .svc-grid, .steps { grid-template-columns: minmax(0, 1fr); }
  .field-grid { grid-template-columns: minmax(0, 1fr); }
  .form-sheet { padding: 26px 20px 30px; }
  .form-no { display: none; }
  /* same 16px floor as the form fields, so tapping the box doesn't zoom */
  .aside-card .track-field input { font-size: 1rem; }
  .confirm-panel { padding: 36px 20px; }
  .confirm-panel .ref-no { padding: 10px 16px; }
  .cert-folder { width: 312px; height: 406px; }
  .cert-paper { width: 285px; min-height: 369px; padding: 20px 18px 24px; }
  .cert-sig { margin-bottom: 22px; }
  /* narrower paper, so the seals give the letterhead type room to fit */
  .cert-letterhead { grid-template-columns: 30px 1fr 30px; gap: 6px; }
  .cert-letterhead .seal { width: 30px; height: 30px; }
  .cert-letterhead .lh-line { font-size: 0.38rem; letter-spacing: 0.04em; }
  .cert-letterhead .lh-brgy { font-size: 0.72rem; }
  /* One card to a row, and a little less air inside it — the gutter is
     already doing the separating on a narrow screen. */
  .bulletin-grid { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .notice-card-body { padding: 18px 18px 0; }
  /* 0.94rem is 15px on a phone, under the floor the rest of the site
     keeps for anything meant to be read rather than glanced at */
  .notice-excerpt p { font-size: 1rem; }
  .notice-cue { margin: 14px 18px 16px; }
  .notice-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  /* The sheet takes the whole screen it is read on, and the two seals give
     way to the middle column rather than squeezing it. */
  .notice-page { padding-block: 18px 44px; }
  .notice-sheet { padding: 24px 20px 28px; }
  .notice-letterhead { grid-template-columns: 40px 1fr 40px; gap: 10px; padding-bottom: 12px; margin-bottom: 18px; }
  .notice-letterhead .seal { width: 40px; height: 40px; }
  .notice-letterhead .lh-line { font-size: 0.5rem; letter-spacing: 0.05em; }
  .notice-letterhead .lh-brgy { font-size: 0.95rem; }
  /* The letterhead has to fit the screen it is read on. A phone cannot hold
     two seals, three lines of agency type and the menu button on one row, so
     the city seal steps out (the barangay seal already identifies the page)
     and the remaining type is set small enough to wrap rather than push the
     page wider than the viewport. */
  .masthead .wrap { gap: 12px; }
  .brand { gap: 10px; }
  .brand .seal { width: 46px; height: 46px; }
  .brand-lines > span { white-space: normal; }
  .brand-lines .republic { font-size: 0.56rem; letter-spacing: 0.1em; }
  /* the barangay's own name never breaks across lines — it shrinks to fit
     the width it is given instead */
  .brand-lines .bname { font-size: clamp(0.98rem, 4.6vw, 1.15rem); white-space: nowrap; }
  .brand-lines .locality { font-size: 0.72rem; line-height: 1.3; }
  .masthead-mark { display: none; }
  .govbar .gov-text { font-size: 0.62rem; }
  .hero-ctas .btn { width: 100%; }

  /* A phone cannot hold four columns of links without setting them too small
     to tap. The two link columns that only repeat what the menu and the
     services page already carry step out; contact details stay, because
     nothing else on a phone gives you the hall's number. Privacy and terms
     stay too — they sit in the bottom rule, below. */
  .footer-grid { grid-template-columns: minmax(0, 1fr); gap: 30px; }
  .footer-col-services,
  .footer-col-government { display: none; }
  .footer-bottom { flex-direction: column; align-items: flex-start; gap: 10px; }
}

/* Narrowest phones still in service (320px). The stamp hangs off the right
   edge of the sheet by design; at this width that edge is the screen edge,
   so it tucks back in rather than being clipped by the hero. */
@media (max-width: 380px) {
  /* 24px of gutter either side is a sixth of a 320px screen — too much to
     spend on margin when the letterhead still has to fit */
  :root { --gutter: 18px; }
  .cert-paper .stamp { right: -6px; }
}
