/* ═══════════════════════════════════════════════════════════════════════════
   POPSI — visual system
   ───────────────────────────────────────────────────────────────────────────
   Plain CSS, no build step. This file is served as-is from public/css/ and
   linked directly by the layout; no Tailwind, no Vite, no npm.

   The theme follows onaindonesia.com: minimal, near-black ink on warm grey,
   pill buttons, generous white space, Bricolage Grotesque for headings and
   Manrope for body text. The accent colours come from the POPSI logo — palm
   leaf green as the working colour, the palm fruit's red-orange reserved for a
   single "currently running" marker per page, exactly as the logo puts one
   fruit on one letter.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Tailwind used to set this through its preflight; now it is explicit. */
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; }
img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }

:root {
    /* Ink & surfaces */
    --ink: #17190f;
    --ink-70: rgba(23, 25, 15, 0.70);
    --ink-50: rgba(23, 25, 15, 0.50);
    --ink-38: rgba(23, 25, 15, 0.38);
    --canvas: #ffffff;
    --surface: #efeeea;
    --surface-deep: #e3e2db;
    --line: rgba(23, 25, 15, 0.12);
    --line-strong: rgba(23, 25, 15, 0.22);

    /* Accents taken from the logo */
    --leaf: #1f7a3d;
    --leaf-deep: #155a2c;
    --leaf-wash: rgba(31, 122, 61, 0.09);
    --fruit: #e2571f;

    /* Rhythm */
    --shell: 1240px;
    --gutter: clamp(20px, 5vw, 56px);
    --band: clamp(64px, 9vw, 128px);
    --radius: 20px;
    --radius-sm: 12px;
    --pill: 999px;

    --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ── base ───────────────────────────────────────────────────────────────── */

html {
    scroll-behavior: smooth;
}

body {
    background: var(--canvas);
    color: var(--ink);
    font-family: 'Manrope', ui-sans-serif, system-ui, sans-serif;
    font-size: 17px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

::selection {
    background: var(--leaf);
    color: #fff;
}

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

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

.skip-link {
    position: absolute;
    left: -9999px;
    top: 8px;
    z-index: 200;
    padding: 10px 18px;
    background: var(--ink);
    color: #fff;
    border-radius: var(--pill);
    font-size: 14px;
}
.skip-link:focus {
    left: 16px;
}

/* ── typography ─────────────────────────────────────────────────────────── */

.display {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -0.03em;
    margin: 0;
    text-wrap: balance;
}

.display-xl { font-size: clamp(2.6rem, 5.6vw, 4.6rem); }
.display-lg { font-size: clamp(2.1rem, 4.2vw, 3.4rem); }
.display-md { font-size: clamp(1.6rem, 2.8vw, 2.35rem); }
.display-sm { font-size: clamp(1.25rem, 1.8vw, 1.5rem); letter-spacing: -0.02em; line-height: 1.15; }

/* Utility labels use Bricolage's narrowed width axis — a small signal that
   this is a marker, not a sentence. */
.kicker {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-stretch: condensed;
    font-weight: 600;
    font-size: 0.7rem;
    letter-spacing: 0.17em;
    text-transform: uppercase;
    color: var(--ink-50);
    display: block;
}
.kicker-leaf { color: var(--leaf); }

.lede {
    font-size: clamp(1.05rem, 1.5vw, 1.2rem);
    line-height: 1.6;
    color: var(--ink-70);
    max-width: 62ch;
    margin: 0;
}

.prose-muted {
    color: var(--ink-70);
    max-width: 68ch;
    margin: 0;
}

/* ── buttons ────────────────────────────────────────────────────────────── */

.btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 13px 26px;
    border: 1px solid transparent;
    border-radius: var(--pill);
    font-family: 'Manrope', sans-serif;
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn-primary {
    background: var(--ink);
    color: #fff;
}
.btn-primary:hover { background: var(--leaf-deep); }

.btn-outline {
    border-color: var(--line-strong);
    color: var(--ink);
}
.btn-outline:hover {
    border-color: var(--ink);
    background: var(--ink);
    color: #fff;
}

.btn-quiet {
    padding-inline: 0;
    color: var(--leaf);
    font-weight: 700;
}
.btn-quiet:hover { color: var(--leaf-deep); }

/* On dark ink the order flips: the primary action becomes a white pill, the
   secondary one a thin outline. */
.btn-light {
    background: #fff;
    color: var(--ink);
}
.btn-light:hover { background: var(--leaf); color: #fff; }

.btn-ghost {
    border-color: rgba(255, 255, 255, 0.28);
    color: rgba(255, 255, 255, 0.92);
}
.btn-ghost:hover { border-color: #fff; background: #fff; color: var(--ink); }

.btn-sm { padding: 9px 18px; font-size: 0.875rem; }

/* A small arrow that shifts on hover — the only motion on a link. */
.btn .icon { width: auto; height: 15px; fill: currentColor; }
.btn .arrow { transition: transform 0.24s var(--ease); }
.btn:hover .arrow { transform: translateX(3px); }

/* ── contact bar + navigation ───────────────────────────────────────────── */

.topbar {
    background: var(--ink);
    color: rgba(255, 255, 255, 0.72);
    font-size: 0.8rem;
}
.topbar-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 20px;
    padding-block: 9px;
}
.topbar a {
    color: inherit;
    text-decoration: none;
    transition: color 0.18s var(--ease);
}
.topbar a:hover { color: #fff; }
.topbar-links { display: flex; gap: 18px; align-items: center; }
.topbar-sep { color: rgba(255, 255, 255, 0.3); }

.masthead {
    position: sticky;
    top: 0;
    z-index: 60;
    background: rgba(255, 255, 255, 0.86);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--line);
}
.masthead-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    min-height: 78px;
}

.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--ink); }
.brand img { height: 50px; width: auto; }
.brand-fallback {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 800;
    font-size: 1.5rem;
    letter-spacing: -0.02em;
}
.brand-sub {
    display: none;
    font-size: 0.82rem;
    line-height: 1.3;
    color: var(--ink-70);
    /* Wide enough to break into two lines rather than three — the text
       block stays shorter than the logo beside it instead of towering. */
    max-width: 27ch;
}
/* Same breakpoint as the desktop menu: once the main nav appears, there is
   room for the organisation's name too. */
@media (min-width: 960px) { .brand-sub { display: block; } }

.mainnav { display: none; align-items: center; gap: 4px; }
@media (min-width: 960px) { .mainnav { display: flex; } }

.navitem { position: relative; }
.navlink {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px;
    border-radius: var(--pill);
    color: var(--ink-70);
    font-size: 0.95rem;
    font-weight: 600;
    text-decoration: none;
    transition: color 0.18s var(--ease), background-color 0.18s var(--ease);
}
.navlink:hover { color: var(--ink); background: var(--surface); }
.navlink[aria-current='page'],
.navitem[data-active='true'] > .navlink { color: var(--leaf); }

.navcaret { transition: transform 0.2s var(--ease); }
.navitem:hover .navcaret,
.navitem:focus-within .navcaret { transform: rotate(180deg); }

.submenu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 246px;
    padding: 8px;
    background: var(--canvas);
    border: 1px solid var(--line);
    border-radius: 16px;
    box-shadow: 0 18px 44px rgba(23, 25, 15, 0.13);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity 0.18s var(--ease), transform 0.18s var(--ease), visibility 0.18s;
}
.navitem:hover > .submenu,
.navitem:focus-within > .submenu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}
.submenu a {
    display: block;
    padding: 10px 14px;
    border-radius: 10px;
    color: var(--ink-70);
    font-size: 0.92rem;
    font-weight: 500;
    text-decoration: none;
    transition: background-color 0.16s var(--ease), color 0.16s var(--ease);
}
.submenu a:hover,
.submenu a[aria-current='page'] { background: var(--surface); color: var(--ink); }

/* The mobile menu uses <details>: opening and closing is native browser
   behaviour, so it still works without JavaScript. `position: static` is
   deliberate so the panel anchors to the sticky .masthead, not to this
   <details>. */
.navdrawer { position: static; }
@media (min-width: 960px) { .navdrawer { display: none; } }

.navtoggle {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 10px 18px;
    border: 1px solid var(--line-strong);
    border-radius: var(--pill);
    background: none;
    color: var(--ink);
    font: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    /* Drop <summary>'s default triangle in every rendering engine. */
    list-style: none;
}
.navtoggle::-webkit-details-marker { display: none; }
.navtoggle::marker { content: ''; }

/* The label changes along with it, without JavaScript. */
.navtoggle-tutup { display: none; }
.navdrawer[open] .navtoggle-buka { display: none; }
.navdrawer[open] .navtoggle-tutup { display: inline; }

.drawer {
    /* Hidden explicitly rather than relying on how <details> hides its
       own contents: absolutely positioned elements escape that internal
       mechanism, and the way they do differs between rendering engines.
       `[open]` is still managed by the browser itself, so this remains
       zero JavaScript. */
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--canvas);
    border-bottom: 1px solid var(--line);
    box-shadow: 0 18px 44px rgba(23, 25, 15, 0.13);
    padding-block: 12px 26px;
    /* A menu taller than the viewport stays scrollable. */
    max-height: calc(100dvh - 100%);
    overflow-y: auto;
}
.navdrawer[open] .drawer { display: block; }
.drawer-group + .drawer-group { border-top: 1px solid var(--line); margin-top: 10px; padding-top: 10px; }
.drawer a {
    display: block;
    padding: 11px 0;
    color: var(--ink);
    font-size: 1.05rem;
    font-weight: 600;
    text-decoration: none;
}
.drawer .drawer-sub a { padding-left: 16px; font-size: 0.95rem; font-weight: 500; color: var(--ink-70); }

/* ── section scaffolding ────────────────────────────────────────────────── */

.band { padding-block: var(--band); }
.band-tight { padding-block: clamp(44px, 6vw, 80px); }
/* Page header: airy above, tight against the content below. */
.band-page { padding-block: clamp(40px, 5.5vw, 72px) clamp(22px, 3vw, 34px); }
.band-surface { background: var(--surface); }
.band-line { border-top: 1px solid var(--line); }

.band-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 18px 32px;
    margin-bottom: clamp(28px, 4vw, 46px);
}
.band-head-text { display: flex; flex-direction: column; gap: 12px; flex: 1 1 460px; }

/* A page header may have a right-hand column (the photo on the profile page).
   Its text column is still the same .band-head-text, so the typeface, sizes and
   spacing never drift away from the other pages. */
.page-head-split { display: grid; gap: clamp(30px, 4.5vw, 60px); }
@media (min-width: 900px) {
    .page-head-split { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); }
}

/* ── hero ───────────────────────────────────────────────────────────────── */

.hero { padding-block: clamp(48px, 7vw, 96px) clamp(56px, 8vw, 104px); }
.hero-grid {
    display: grid;
    gap: clamp(32px, 5vw, 64px);
    align-items: center;
}
@media (min-width: 900px) {
    .hero-grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
}
.hero-text { display: flex; flex-direction: column; gap: 24px; align-items: flex-start; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; }

.hero-figure {
    position: relative;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--surface-deep);
    aspect-ratio: 4 / 5;
}
.hero-figure img { width: 100%; height: 100%; object-fit: cover; }

/* POPSI's photo archive is shown in full colour everywhere — hero, gallery
   strip, album covers. Hover only brings a slight zoom. */
.doc-photo { transition: transform 0.5s var(--ease); }
.doc-frame:hover .doc-photo,
.doc-frame:focus-visible .doc-photo { transform: scale(1.03); }

/* ── statistics ─────────────────────────────────────────────────────────── */

.stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
}
.stat { padding: clamp(24px, 3.5vw, 40px) 0; }
.stat + .stat { border-left: 1px solid var(--line); padding-left: clamp(14px, 3vw, 36px); }
.stat-figure {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 700;
    font-size: clamp(1.9rem, 4vw, 3.4rem);
    line-height: 1;
    letter-spacing: -0.04em;
}
.stat-label { margin-top: 10px; }

/* ── event cards: the edition spine ─────────────────────────────────────── */

.edition-grid {
    display: grid;
    gap: clamp(20px, 2.6vw, 32px);
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.edition {
    display: flex;
    flex-direction: column;
    gap: 16px;
    text-decoration: none;
    color: inherit;
}
.edition-frame {
    position: relative;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--surface-deep);
    aspect-ratio: 3 / 4;
    transition: box-shadow 0.28s var(--ease), transform 0.28s var(--ease);
}
.edition:hover .edition-frame,
.edition:focus-visible .edition-frame {
    transform: translateY(-4px);
    box-shadow: 0 20px 44px rgba(23, 25, 15, 0.16);
}
.edition-frame img {
    width: 100%;
    height: 100%;
    /* A flyer is a poster — show it whole, do not crop it like a photo. */
    object-fit: contain;
    background: var(--surface);
}

/* The edition number (6TH, 5TH …) — the event page's main marker. IPOSC really
   is numbered in sequence, so this number carries information, not decoration. */
.edition-ordinal {
    position: absolute;
    left: 0;
    bottom: 0;
    padding: 10px 16px 8px;
    background: var(--canvas);
    border-top-right-radius: 14px;
    font-family: 'Bricolage Grotesque', sans-serif;
    font-stretch: condensed;
    font-weight: 800;
    font-size: clamp(1.6rem, 2.4vw, 2.1rem);
    line-height: 0.9;
    letter-spacing: -0.02em;
}
.edition-live .edition-ordinal { color: var(--fruit); }

.edition-body { display: flex; flex-direction: column; gap: 6px; }
.edition-title { font-size: 1rem; font-weight: 700; line-height: 1.3; }
.edition-meta { display: flex; align-items: center; gap: 8px; font-size: 0.82rem; color: var(--ink-50); }

.filterbar { display: flex; flex-wrap: wrap; gap: 8px; }
.filter {
    padding: 9px 18px;
    border: 1px solid var(--line-strong);
    border-radius: var(--pill);
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--ink-70);
    text-decoration: none;
    transition: all 0.18s var(--ease);
}
.filter:hover { border-color: var(--ink); color: var(--ink); }
.filter[aria-current='true'] { background: var(--ink); border-color: var(--ink); color: #fff; }

/* ── board list ─────────────────────────────────────────────────────────── */

.roster { border-top: 2px solid var(--ink); }
.roster-row {
    display: grid;
    gap: 4px 32px;
    padding-block: clamp(20px, 2.6vw, 28px);
    border-bottom: 1px solid var(--line);
}
@media (min-width: 720px) {
    .roster-row { grid-template-columns: 240px minmax(0, 1fr); align-items: baseline; }
}
.roster-role { padding-top: 4px; }
.roster-name {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 700;
    font-size: clamp(1.3rem, 2.2vw, 1.75rem);
    letter-spacing: -0.02em;
    line-height: 1.2;
}
.roster-list { display: flex; flex-direction: column; gap: 10px; }
.roster-list-item { display: flex; gap: 14px; align-items: baseline; }
.roster-index {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-stretch: condensed;
    font-size: 0.85rem;
    color: var(--ink-38);
    min-width: 1.4em;
}

/* ── membership ─────────────────────────────────────────────────────────── */

.member-grid {
    display: grid;
    gap: clamp(14px, 2vw, 24px);
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
}
.member {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: clamp(20px, 2.6vw, 30px) 18px;
    background: var(--canvas);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    text-align: center;
    transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.member:hover { border-color: var(--line-strong); transform: translateY(-2px); }
.member-mark {
    display: grid;
    place-items: center;
    width: 84px;
    height: 84px;
    border-radius: var(--pill);
    background: var(--surface);
    overflow: hidden;
}
.member-mark img { width: 100%; height: 100%; object-fit: contain; padding: 10px; }
.member-mark-initials {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-stretch: condensed;
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--ink-50);
}
.member-name { font-size: 0.95rem; font-weight: 700; line-height: 1.25; }
.member-full { font-size: 0.78rem; color: var(--ink-50); line-height: 1.4; }

/* ── gallery ────────────────────────────────────────────────────────────── */

.album-grid {
    display: grid;
    gap: clamp(20px, 2.6vw, 30px);
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.album { display: flex; flex-direction: column; gap: 14px; text-decoration: none; color: inherit; }
.album-frame {
    position: relative;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--surface-deep);
    aspect-ratio: 4 / 3;
}
.album-frame img { width: 100%; height: 100%; object-fit: cover; }
.album-title { font-size: 1.05rem; font-weight: 700; line-height: 1.3; }

.photo-grid {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.photo-tile {
    position: relative;
    display: block;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--surface-deep);
    aspect-ratio: 1;
    cursor: zoom-in;
}
.photo-tile img { width: 100%; height: 100%; object-fit: cover; }

/* The homepage gallery strip — scrolls sideways, one photo per album. */
.strip {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    padding-inline: var(--gutter);
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}
.strip::-webkit-scrollbar { display: none; }
.strip-item {
    position: relative;
    flex: none;
    width: clamp(200px, 26vw, 290px);
    aspect-ratio: 4 / 3;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--surface-deep);
    scroll-snap-align: start;
    text-decoration: none;
}
.strip-item img { width: 100%; height: 100%; object-fit: cover; }
.strip-caption {
    position: absolute;
    inset: auto 0 0 0;
    padding: 22px 14px 12px;
    background: linear-gradient(to top, rgba(23, 25, 15, 0.85), transparent);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 600;
}

/* ── lightbox ───────────────────────────────────────────────────────────── */

/* The overlay is opened through :target — the URL fragment decides which photo
   is shown. No JavaScript is involved, so clicking a photo opens this overlay
   instead of navigating to the image file.

   The element carrying the fragment id is the anchor below, not the overlay
   itself. That anchor has zero size and fixed positioning so it always counts
   as already in view; without it the browser scrolls the page to the target
   element and the visitor's reading position is lost every time the overlay
   opens or closes. */
.lightbox-anchor {
    position: fixed;
    top: 0;
    left: 0;
    width: 0;
    height: 0;
    overflow: hidden;
}

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 120;
    display: none;
    place-items: center;
    padding: clamp(12px, 3vw, 40px);
}
.lightbox-anchor:target + .lightbox { display: grid; }


/* The dark backdrop doubles as the click target that closes the overlay. No
   backdrop-filter: at 0.94 opacity the blur is practically invisible, while the
   effect forces its own compositing layer and has rendered in bands. */
.lightbox-scrim {
    position: absolute;
    inset: 0;
    background: rgba(14, 15, 10, 0.96);
}

.lightbox-figure {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: 14px;
    align-items: center;
    max-width: min(1200px, 100%);
    max-height: 100%;
    margin: 0;
}
.lightbox-image {
    width: min(1200px, 92vw);
    height: calc(100dvh - 170px);
    background-position: center;
    background-repeat: no-repeat;
    background-size: contain;
}

.lightbox-file {
    color: #fff;
    text-decoration: underline;
    text-underline-offset: 3px;
    margin-left: 10px;
}
.lightbox-file:hover { color: var(--leaf); }

.lightbox-bar {
    display: flex;
    align-items: center;
    gap: clamp(12px, 3vw, 24px);
    color: rgba(255, 255, 255, 0.72);
    font-size: 0.85rem;
    text-align: center;
}

.lightbox-btn {
    display: grid;
    place-items: center;
    flex: none;
    width: 46px;
    height: 46px;
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: var(--pill);
    background: none;
    color: #fff;
    text-decoration: none;
    transition: background-color 0.18s var(--ease), border-color 0.18s var(--ease);
}
.lightbox-btn:hover { background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.5); }
.lightbox-btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.lightbox-close {
    position: absolute;
    z-index: 2;
    top: clamp(12px, 3vw, 32px);
    right: clamp(12px, 3vw, 32px);
}

/* ── news ───────────────────────────────────────────────────────────────── */

.news-grid {
    display: grid;
    gap: clamp(22px, 3vw, 34px);
    grid-template-columns: repeat(auto-fit, minmax(288px, 1fr));
}
.news-card { display: flex; flex-direction: column; gap: 16px; text-decoration: none; color: inherit; }
.news-frame {
    position: relative;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--surface-deep);
    aspect-ratio: 16 / 10;
}
.news-frame img { width: 100%; height: 100%; object-fit: cover; }
.news-title {
    font-size: 1.08rem;
    font-weight: 700;
    line-height: 1.35;
    transition: color 0.18s var(--ease);
}
.news-card:hover .news-title { color: var(--leaf); }
.news-excerpt { font-size: 0.92rem; color: var(--ink-70); line-height: 1.55; }
.news-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 0.78rem; color: var(--ink-50); }
.news-excerpt mark, .article-excerpt mark {
    background: var(--leaf-wash);
    color: var(--leaf-deep);
    padding: 0 2px;
    border-radius: 3px;
}

.news-list { display: flex; flex-direction: column; }
.news-row {
    display: grid;
    gap: 18px;
    grid-template-columns: 108px minmax(0, 1fr);
    padding-block: 22px;
    border-bottom: 1px solid var(--line);
    text-decoration: none;
    color: inherit;
}
@media (min-width: 720px) { .news-row { grid-template-columns: 190px minmax(0, 1fr); gap: 28px; } }
.news-row:hover .news-title { color: var(--leaf); }
.news-row-frame {
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--surface-deep);
    aspect-ratio: 4 / 3;
}
.news-row-frame img { width: 100%; height: 100%; object-fit: cover; }

/* Articles: we only show an excerpt and point readers to the source. */
.article-lede { max-width: 72ch; }
.article-frame {
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--surface-deep);
    aspect-ratio: 16 / 9;
}
.article-frame img { width: 100%; height: 100%; object-fit: cover; }
.article-excerpt {
    border-left: 3px solid var(--leaf);
    padding: 4px 0 4px 22px;
    font-size: 1.1rem;
    line-height: 1.65;
    color: var(--ink-70);
    max-width: 68ch;
}
.source-note {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px 20px;
    padding: clamp(20px, 3vw, 28px);
    background: var(--surface);
    border-radius: var(--radius);
}

/* ── contact: channel board ─────────────────────────────────────────────── */

/* Contact channels do not carry equal weight, so neither do their cards. The
   secretariat's number gets a dark-ink card with the digits set as large as a
   heading; email and social media become white rows whose whole surface is
   clickable — not a box containing a small button. */

.channel-board {
    display: grid;
    gap: clamp(14px, 2vw, 22px);
}
@media (min-width: 940px) {
    .channel-board { grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr); }
    /* The channel rows follow the main card's height so both columns stop
       on the same line — rather than the right column hanging half-way. */
    .channel-list { height: 100%; grid-auto-rows: 1fr; }
    .channel-place { grid-column: 1 / -1; }
}

/* Main card */

.channel-lead {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    padding: clamp(26px, 3.4vw, 42px);
    background: var(--ink);
    border-radius: var(--radius);
    color: rgba(255, 255, 255, 0.68);
}
.channel-lead .kicker { color: rgba(255, 255, 255, 0.42); }
.channel-lead .hero-actions { margin-top: 6px; }

.channel-lead-value {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 700;
    font-size: clamp(1.7rem, 3.4vw, 2.55rem);
    letter-spacing: -0.03em;
    line-height: 1.05;
    color: #fff;
    word-break: break-word;
}
.channel-lead-note {
    margin: 0;
    max-width: 42ch;
    font-size: 0.94rem;
    line-height: 1.6;
}

/* Channel rows */

.channel-list {
    display: grid;
    gap: clamp(12px, 1.5vw, 16px);
}
.channel {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 18px;
    padding: clamp(16px, 2vw, 20px) clamp(18px, 2.4vw, 24px);
    background: var(--canvas);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: inherit;
    text-decoration: none;
    transition: border-color 0.24s var(--ease), box-shadow 0.24s var(--ease), transform 0.24s var(--ease);
}
.channel:hover,
.channel:focus-visible {
    border-color: transparent;
    box-shadow: 0 16px 34px rgba(23, 25, 15, 0.13);
    transform: translateY(-2px);
}

.channel-glyph {
    display: grid;
    place-items: center;
    flex: none;
    width: 46px;
    height: 46px;
    border-radius: 14px;
    background: var(--leaf-wash);
    color: var(--leaf);
    transition: background-color 0.24s var(--ease), color 0.24s var(--ease);
}
.channel:hover .channel-glyph,
.channel:focus-visible .channel-glyph {
    background: var(--leaf);
    color: #fff;
}
/* Optical height per glyph, not one identical box for all of them. */
.channel-glyph svg { width: auto; height: 18px; }
.channel-glyph .icon-instagram { height: 19px; }
.channel-glyph .icon-facebook  { height: 17px; }
.channel-glyph .icon-envelope  { height: 15px; }
.channel-glyph .icon-pin       { height: 19px; }

.channel-text {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.channel-value {
    font-weight: 700;
    font-size: 1.02rem;
    letter-spacing: -0.01em;
    line-height: 1.35;
    overflow-wrap: anywhere;
}
.channel .arrow {
    color: var(--ink-38);
    transition: transform 0.24s var(--ease), color 0.24s var(--ease);
}
.channel:hover .arrow,
.channel:focus-visible .arrow { color: var(--ink); transform: translateX(3px); }

/* A channel that opens another site tilts its arrow off the page. */
.channel-out .arrow { transform: rotate(-45deg); }
.channel-out:hover .arrow,
.channel-out:focus-visible .arrow { transform: rotate(-45deg) translateX(3px); }

/* On narrow screens the glyph chip shrinks so its value is not left truncated. */
@media (max-width: 460px) {
    .channel { gap: 14px; padding-inline: 16px; }
    .channel-glyph { width: 42px; height: 42px; border-radius: 12px; }
    .channel-value { font-size: 0.96rem; }
}

/* Address & map */

.channel-place {
    display: flex;
    flex-direction: column;
    gap: clamp(16px, 2vw, 22px);
    padding: clamp(18px, 2.4vw, 24px);
    background: var(--canvas);
    border: 1px solid var(--line);
    border-radius: var(--radius);
}
.channel-place-text { display: flex; align-items: center; gap: 18px; }
.map-frame { border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--line); aspect-ratio: 16 / 7; }
.map-frame iframe { width: 100%; height: 100%; border: 0; display: block; }

/* ── empty boxes (before media is imported) ─────────────────────────────── */

.placeholder {
    display: grid;
    place-items: center;
    width: 100%;
    height: 100%;
    padding: 16px;
    background:
        repeating-linear-gradient(45deg, var(--surface) 0 8px, var(--surface-deep) 8px 16px);
    color: var(--ink-38);
    font-family: 'Bricolage Grotesque', sans-serif;
    font-stretch: condensed;
    font-size: 0.72rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-align: center;
}

.notice {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 16px;
    padding: 16px 22px;
    border: 1px dashed var(--line-strong);
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    color: var(--ink-70);
}

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    padding: clamp(32px, 5vw, 56px);
    background: var(--surface);
    border-radius: var(--radius);
}

/* ── layout helpers ─────────────────────────────────────────────────────── */

.feature-card {
    margin-bottom: clamp(32px, 4vw, 48px);
    padding-bottom: clamp(32px, 4vw, 48px);
    border-bottom: 1px solid var(--line);
}
@media (min-width: 860px) {
    .feature-card {
        display: grid;
        grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
        gap: 12px 40px;
        align-items: start;
    }
    .feature-card .article-frame { grid-row: 1 / span 3; aspect-ratio: 4 / 3; }
}
.after-band { margin-top: clamp(26px, 3.5vw, 40px); }
.tight-text { gap: 6px; }

/* ── pagination ─────────────────────────────────────────────────────────── */

.pager { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pager-link,
.pager-gap {
    display: grid;
    place-items: center;
    min-width: 44px;
    height: 44px;
    padding-inline: 14px;
    border: 1px solid var(--line-strong);
    border-radius: var(--pill);
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--ink-70);
    text-decoration: none;
    transition: all 0.18s var(--ease);
}
.pager-link:hover { border-color: var(--ink); color: var(--ink); }
.pager-link[aria-current='page'] { background: var(--ink); border-color: var(--ink); color: #fff; }
.pager-gap, .pager-link[aria-disabled='true'] { opacity: 0.4; pointer-events: none; }

/* ── footer ─────────────────────────────────────────────────────────────── */

.footer { background: var(--ink); color: rgba(255, 255, 255, 0.72); }
.footer-top {
    display: grid;
    gap: clamp(32px, 4vw, 56px);
    padding-block: clamp(48px, 7vw, 84px);
}
@media (min-width: 860px) { .footer-top { grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.7fr) minmax(0, 0.95fr); } }
.footer .kicker { color: rgba(255, 255, 255, 0.45); }
.footer-statement {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 600;
    font-size: clamp(1.25rem, 2.2vw, 1.7rem);
    line-height: 1.25;
    letter-spacing: -0.02em;
    color: #fff;
    max-width: 24ch;
    margin: 0;
}
.footer-col { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.footer-nav a { font-weight: 600; }
.footer-nav a[aria-current] { color: #fff; }

.footer a { color: rgba(255, 255, 255, 0.72); text-decoration: none; transition: color 0.18s var(--ease); }
.footer a:hover { color: #fff; }

/* Social icons — solid chips, the only circular shape in the footer. The brand
   glyphs are used intact (not redrawn in an outline style) so they are
   recognised instantly at small sizes; the selectors are paired with .footer so
   they are not outranked by the .footer a rule above. */
.footer-social { margin-top: 14px; }
.social-row { display: flex; gap: 10px; }
.footer .social-btn {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: var(--pill);
    background: rgba(255, 255, 255, 0.10);
    color: rgba(255, 255, 255, 0.92);
    transition: color 0.18s var(--ease), background-color 0.18s var(--ease),
                transform 0.18s var(--ease);
}
.footer .social-btn:hover {
    color: #fff;
    background: var(--leaf);
    transform: translateY(-2px);
}
/* A green focus ring all but disappears on dark ink. */
.footer .social-btn:focus-visible { outline-color: #fff; }
.social-btn svg { width: auto; fill: currentColor; }

/* Height is tuned per icon: Instagram's camera is square, Facebook's f is
   narrow and tall — optical sizing, not one identical box. */
.social-btn .icon-instagram { height: 21px; }
.social-btn .icon-facebook  { height: 18px; }
.footer-bottom {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px 24px;
    padding-block: 22px;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.45);
}

/* ── motion ─────────────────────────────────────────────────────────────── */

/* Two layers of motion, and both are purely decorative.

   `.rise` — plays once when the page opens; used by the page header. Pure CSS,
   so it runs even if app.js fails to load.

   `.reveal` / `.reveal-anak` — plays when a block enters the viewport; needs the
   observer in app.js. Its initial state hides the content, so the rules are
   deliberately gated behind `[data-gerak='on']`, which only the inline script in
   <head> sets. Without JS, with failing JS, or when the reader asks for reduced
   motion, that marker never appears and all content shows as-is — the page never
   ends up blank because of an animation.

   The displacement uses the `translate` property, not `transform`. The two are
   separate in the cascade, so the small hover lift on .member and .path-card —
   which are direct children of a revealing grid — stays alive and the two do not
   overwrite each other. */

.rise { animation: rise 0.7s var(--ease) both; }
.rise-2 { animation-delay: 0.08s; }
.rise-3 { animation-delay: 0.16s; }
.rise-4 { animation-delay: 0.24s; }

@keyframes rise {
    from { opacity: 0; transform: translateY(14px); }
    to { opacity: 1; transform: none; }
}

[data-gerak='on'] .reveal,
[data-gerak='on'] .reveal-anak > * {
    opacity: 0;
    translate: 0 22px;
    transition: opacity 0.62s var(--ease), translate 0.62s var(--ease);
    transition-delay: var(--tunda, 0s);
}

[data-gerak='on'] .reveal.tampil,
[data-gerak='on'] .reveal-anak.tampil > * {
    opacity: 1;
    translate: none;
}

/* Grid children follow one after another. The stagger stops at the eighth
   child: an album can hold dozens of photos, and without this cap the last one
   would only appear several seconds after the first. */
[data-gerak='on'] .reveal-anak > *:nth-child(2) { --tunda: 0.06s; }
[data-gerak='on'] .reveal-anak > *:nth-child(3) { --tunda: 0.12s; }
[data-gerak='on'] .reveal-anak > *:nth-child(4) { --tunda: 0.18s; }
[data-gerak='on'] .reveal-anak > *:nth-child(5) { --tunda: 0.24s; }
[data-gerak='on'] .reveal-anak > *:nth-child(6) { --tunda: 0.30s; }
[data-gerak='on'] .reveal-anak > *:nth-child(7) { --tunda: 0.36s; }
[data-gerak='on'] .reveal-anak > *:nth-child(n+8) { --tunda: 0.42s; }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }
    /* The `data-gerak` marker is set once on load. If the reader changes
       their setting afterwards, this rule is what makes sure no block is
       left stranded invisible. */
    [data-gerak='on'] .reveal,
    [data-gerak='on'] .reveal-anak > * { opacity: 1; translate: none; }
}

/* ── profile page ───────────────────────────────────────────────────────── */
/* What is specific to the "About" page: the key-facts table and the archive
   photo filling the header's right-hand column. The header pattern itself —
   typeface, sizes, spacing — comes from .band-head-text in the "section
   scaffolding" part above. This section sits after all the shared classes, so
   the tweaks below are allowed to override .display and .prose-muted. */

/* Key facts: a heavy rule on top like a table head, then evenly spaced
   label–value rows. The distance from the heading follows .band-head-text's own
   12px gap, plus a little room so the rule does not sit flush against it. */
.spec {
    width: 100%;
    margin: 10px 0 0;
    border-top: 2px solid var(--ink);
}
.spec-row {
    display: grid;
    grid-template-columns: minmax(104px, 0.42fr) minmax(0, 1fr);
    gap: 4px 24px;
    align-items: baseline;
    padding-block: 13px;
    border-bottom: 1px solid var(--line);
}
.spec-label { padding-top: 3px; }
.spec-value { margin: 0; font-size: 0.98rem; font-weight: 600; }

.profil-figure { margin: 0; display: flex; flex-direction: column; gap: 12px; }
.profil-frame {
    position: relative;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--surface-deep);
    aspect-ratio: 4 / 5;
}
.profil-frame img { width: 100%; height: 100%; object-fit: cover; }
/* On wide screens the photo follows the text column's height, so both columns
   line up at the top and the bottom; below that the photo returns to a 4:5
   ratio. This rule must come after .profil-frame above for the ratio to actually
   be overridden. */
@media (min-width: 900px) {
    .profil-figure { height: 100%; }
    .profil-frame { flex: 1; aspect-ratio: auto; min-height: 400px; }
}
.profil-caption {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 0.8rem;
    color: var(--ink-50);
}
.profil-caption::before {
    content: '';
    flex: none;
    width: 20px;
    height: 1px;
    background: var(--line-strong);
}

/* ── mandate: vision, mission, role ─────────────────────────────────────── */
/* One quiet block in the middle of the page. The vision leads — set apart by
   size, a border and space, not by a dark background or colour inside the
   sentence. Mission and role stand below it as two parallel columns. */

.mandate { display: flex; flex-direction: column; gap: clamp(30px, 4.5vw, 58px); }

.mandate-lead {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding-left: clamp(18px, 2.4vw, 30px);
    border-left: 2px solid var(--leaf);
}
.mandate-visi {
    max-width: 34ch;
    font-size: clamp(1.45rem, 2.8vw, 2.3rem);
    line-height: 1.25;
    letter-spacing: -0.02em;
}

.mandate-pair { display: grid; gap: clamp(24px, 4vw, 56px); }
@media (min-width: 760px) {
    .mandate-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.mandate-col {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-top: 20px;
    border-top: 1px solid var(--line-strong);
}
.mandate-col p { max-width: 46ch; }

/* ── member emblems ─────────────────────────────────────────────────────── */

.coalition {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: clamp(22px, 3vw, 44px);
}
.coalition-text { display: flex; flex-direction: column; gap: 10px; flex: 1 1 260px; }
.coalition-marks {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin: 0;
    padding: 0;
    list-style: none;
    flex: 1 1 340px;
}
.coalition-mark {
    display: grid;
    place-items: center;
    width: 68px;
    height: 68px;
    border-radius: var(--pill);
    background: var(--canvas);
    border: 1px solid var(--line);
    overflow: hidden;
}
.coalition-mark img { width: 100%; height: 100%; object-fit: contain; padding: 10px; }
.coalition-mark .member-mark-initials { font-size: 0.78rem; padding: 6px; text-align: center; }

/* ── two ways forward ───────────────────────────────────────────────────── */

.pathway { display: grid; gap: clamp(16px, 2.4vw, 24px); }
@media (min-width: 760px) {
    .pathway { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.path-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    padding: clamp(24px, 3vw, 34px);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    text-decoration: none;
    color: inherit;
    transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.path-card:hover { border-color: var(--line-strong); transform: translateY(-2px); }
.path-title { transition: color 0.2s var(--ease); }
.path-card:hover .path-title { color: var(--leaf); }
.path-note { font-size: 0.9rem; color: var(--ink-70); }
.path-card .arrow {
    margin-top: 8px;
    color: var(--leaf);
    transition: transform 0.24s var(--ease);
}
.path-card:hover .arrow { transform: translateX(4px); }
