/* ============================================================================
   dswd-surfaces.css — one surface treatment for the whole system

   Three things, applied everywhere:

     1. Panel containers lose their border. Depth now comes from elevation and
        a slightly lifted background, not an outline. Borders that carry
        *meaning* — form field edges, focus rings, table row separators,
        section rules, status accent bars — are deliberately preserved, because
        removing those would cost clarity rather than buy calm.

     2. Message containers (alerts, notes, callouts) become transparent: a
        translucent tint of their own semantic colour instead of a solid fill,
        with the colour carried by the icon, the text and a left accent bar.

     3. Every panel class in the codebase — .panel, .card, .mod-card, .kpi,
        .sec-card, .card-citizen, .svc-card, .cs-card, .album, and the rest —
        resolves to the same radius, padding rhythm, background and shadow, so
        a card looks the same whichever page it appears on.

   Loaded last, after every other stylesheet.
   ========================================================================= */

:root{
  /* One surface, one elevation ramp, used by every panel below. */
  --surface-bg:        #ffffff;
  --surface-bg-alt:    #fbfcfe;
  --surface-radius:    16px;
  --surface-radius-sm: 12px;
  --surface-pad:       22px;

  /* Elevation replaces the borders. Two very soft layers read as a raised
     edge without drawing a line. */
  --surface-rest:  0 1px 2px rgba(16,20,28,.04), 0 4px 14px rgba(16,20,28,.06);
  --surface-hover: 0 2px 4px rgba(16,20,28,.05), 0 12px 30px rgba(16,20,28,.10);
  --surface-sunk:  inset 0 1px 2px rgba(16,20,28,.05);
}

/* ═══════════════════════════════════════════════════════════════════════
   1 + 3. PANELS — no border, one consistent treatment
   ═══════════════════════════════════════════════════════════════════════ */
.panel,
.card,
.mod-card,
.card-citizen,
.sec-card,
.reg-card,
.kpi,
.stat-card,
.mod-stat-card,
.svc-card,
.cs-card,
.album,
.event-block,
.dir-person,
.dd-card,
.dd-item,
.svc-facility,
.tp-item,
.news-card,
.prog-cat-card,
.prog-row-item,
.testimonial-card,
.office-card,
.step-card,
.achievement-card,
.featured-card,
.adv-table-wrap,
.video-embed,
.dswd-ag-card,
.prog-cell,
.role-card,
.dswd-stat,
.dswd-card,
.ds-card{
  border: none !important;
  border-radius: var(--surface-radius);
  background: var(--surface-bg);
  box-shadow: var(--surface-rest);
  transition: box-shadow .2s ease, transform .2s ease;
}

/* Interactive panels lift; static ones stay put. */
.kpi:hover,
.card:hover,
.mod-card:hover,
.svc-card:hover,
.cs-card:hover,
.news-card:hover,
.prog-cat-card:hover,
.prog-row-item:hover,
.testimonial-card:hover,
.office-card:hover,
.step-card:hover,
.achievement-card:hover,
.dir-person:hover,
.dswd-ag-card:hover,
.tp-item:hover{
  box-shadow: var(--surface-hover);
}

/* Nested panels sit on the tinted surface so they read as *inside* their
   parent rather than as another floating card. */
.panel .dd-item,
.panel .svc-facility,
.panel .dd-card,
.mod-card .svc-facility,
.svc-card .svc-facility,
.cs-card .cs-where,
.album .album-thumb{
  background: var(--surface-bg-alt);
  box-shadow: none;
  border-radius: var(--surface-radius-sm);
}

/* The accent stripe stays on the service cards, where it distinguishes one
   programme from another. It is gone from the dashboard KPI tiles: there the
   icon already carries the colour, and against a borderless tile the 4px edge
   was reading as exactly the border it was meant to replace. */
.svc-card{ box-shadow: inset 4px 0 0 var(--svc, transparent), var(--surface-rest) !important; }
.cs-card { box-shadow: inset 4px 0 0 var(--cs,  transparent), var(--surface-rest) !important; }
.svc-card:hover{ box-shadow: inset 4px 0 0 var(--svc, transparent), var(--surface-hover) !important; }
.cs-card:hover { box-shadow: inset 4px 0 0 var(--cs,  transparent), var(--surface-hover) !important; }
.kpi      { box-shadow: var(--surface-rest) !important; }
.kpi:hover{ box-shadow: var(--surface-hover) !important; }
/* The ::before stripe some cards used is now redundant. */
.kpi::before{ display: none !important; }

/* Panel headers and footers: a hairline of tinted background, not a rule. */
.panel-head,
.mod-card-header,
.svc-body,
.news-footer,
.prog-cat-footer,
.cs-body{
  border: none !important;
}
.panel-head,
.mod-card-header{
  background: var(--surface-bg-alt);
  border-radius: var(--surface-radius) var(--surface-radius) 0 0;
}
/* Inside an expanded card the divider still helps, so keep a faint one. */
.svc-body, .cs-body{ box-shadow: inset 0 1px 0 rgba(16,20,28,.06); }

/* Panels that were only ever a border now need a background to exist at all. */
.adv-table-wrap, .video-embed{ overflow: hidden; }

/* Safety net. New markup and per-page styles keep inventing card classes, so
   rather than chase each one, anything named like a panel loses its border
   too. Scoped to elements that are not form controls, so an input named
   .search-card-input keeps the edge that makes it look editable. */
[class*="card"]:not(input):not(select):not(textarea):not(button):not(.btn):not([class*="cardholder"]),
[class*="panel"]:not(input):not(select):not(textarea):not(button):not(.btn),
[class*="-box"]:not(input):not(select):not(textarea):not(button):not(.btn),
[class*="tile"]:not(input):not(select):not(textarea):not(button):not(.btn){
  border-color: transparent !important;
}

/* Inline border styles written straight onto an element also go. */
[style*="border:1px solid"], [style*="border: 1px solid"],
[style*="border:1.5px solid"], [style*="border: 1.5px solid"]{
  border-color: transparent !important;
}
/* …except on the controls where the edge is the affordance. */
input[style*="border"], select[style*="border"], textarea[style*="border"]{
  border-color: rgba(16,20,28,.18) !important;
}

/* ── Borders that carry meaning and must NOT be removed ───────────────── */
input, select, textarea,
.input-grp input, .input-grp select,
.form-control, .form-select,
.ux-segmented label,
.ux-chip-toggle,
.dp-head select{
  border-width: 1.5px !important;
  border-style: solid !important;
}

/* …except where the field wrapper draws the border instead. These searches are
   a flex row whose outline lives on the container, so forcing a border back
   onto the input draws a second box inside the first — and, with the input
   inheriting white text colour, a white one.

   .dswd-searchbar is the shared component from includes/search_bar.php and was
   missing from this list, so every page that adopted it — beneficiaries,
   documents, scheduling, grievance, 4Ps, calendar, users, import, social
   pension — drew the doubled box. The four below it are the older per-page
   wrappers that predate the shared one. */
.dswd-searchbar input,
.dswd-sb-search input, .cz-search input,
.dswd-topsearch input, .mod-search input{
  border: none !important;
  background: transparent !important;
  box-shadow: none !important;
}
*:focus-visible{ outline-style: solid !important; }

/* Table rows still need their separators to be readable. */
.q-table td, .adv-table td, .dir-grid td, table.table td, table.table th{
  border-top: 1px solid rgba(16,20,28,.07) !important;
}

/* Deliberate section rules stay. */
.svc-cat-head, .event-head, .month-head .month-rule, .footer-divider, hr{
  border-bottom-width: initial;
}
.svc-cat-head{ border-bottom: 2px solid rgba(16,20,28,.08) !important; }
.event-head  { border-bottom: 2px solid rgba(16,20,28,.08) !important; }

/* ═══════════════════════════════════════════════════════════════════════
   2. MESSAGES — transparent panels
   A solid block of colour shouts; a translucent tint with a coloured accent
   says the same thing without taking over the page.
   ═══════════════════════════════════════════════════════════════════════ */
.alert,
.alert-citizen,
.dash-note,
.cms-note,
.svc-note,
.cs-note,
.dd-note,
.ci-note,
.ux-status,
.ds-alert,
.invalid-feedback,
.error-message{
  background: transparent !important;
  border: none !important;
  border-radius: var(--surface-radius-sm);
  box-shadow: none !important;
  padding: 13px 18px;
  backdrop-filter: none;
}

/* A very light wash of the message's own colour, so it still reads as a
   block without becoming a solid slab. `color-mix` where supported, with a
   plain rgba fallback for older engines. */
@supports (background: color-mix(in srgb, red 8%, transparent)){
  .alert, .alert-citizen, .dash-note, .cms-note, .svc-note,
  .cs-note, .dd-note, .ci-note, .ux-status, .ds-alert{
    background: color-mix(in srgb, currentColor 6%, transparent) !important;
  }
}

/* Semantic colour is carried by the text and the accent, not a fill. */
.alert-success, .alert.ok, .alert.success,
.dash-note.ok, .cms-note.ok, .ds-alert--success{ color: #15803d !important; }
.alert-danger, .alert.err, .alert.error, .alert-citizen.danger,
.ds-alert--danger, .invalid-feedback, .error-message{ color: #c0392b !important; }
.alert-warning, .alert.warn, .dash-note.warn, .cms-note.warn,
.ds-alert--warning{ color: #b45309 !important; }
.alert-info, .alert.info, .dash-note.info, .cms-note.info,
.alert-citizen.info, .ux-status, .ds-alert--info{ color: #1d4ed8 !important; }

/* Body copy inside a message stays readable rather than inheriting the full
   semantic hue at paragraph length. */
.alert span, .alert p,
.dash-note span, .cms-note span, .svc-note span, .cs-note span{
  color: inherit;
  opacity: .92;
}
.alert strong, .dash-note strong, .cms-note strong,
.svc-note strong, .cs-note strong{ opacity: 1; }

/* Bootstrap paints its own alert backgrounds; override those too. */
.alert-dismissible, .alert.fade, .alert.show{ background: transparent !important; }
.alert .btn-close{ opacity: .5; }

/* Toasts keep a solid surface — they float over content and would be
   unreadable at 7% opacity. */
.toast-stack .toast, .ds-toast{
  background: var(--surface-bg) !important;
  box-shadow: var(--surface-hover) !important;
  border: none !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   INTRO SPLASH — aura + glitter behind the DSWD Region III seal
   Shown once per browser session on first arrival (see dswd-intro.js).
   ═══════════════════════════════════════════════════════════════════════ */
.dswd-intro{
  position: fixed; inset: 0; z-index: 3000;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(120% 120% at 50% 45%, #0d2a55 0%, #071731 55%, #04101f 100%);
  overflow: hidden;
  transition: opacity .7s ease, visibility .7s;
}
.dswd-intro.done{ opacity: 0; visibility: hidden; pointer-events: none; }

.dswd-intro-bg{ position:absolute; inset:0; z-index:0; overflow:hidden; }
.dswd-intro-frame{
  position:absolute; inset:0;
  background-size:cover; background-position:center; background-repeat:no-repeat;
  opacity:0; transform:scale(1.12);
  transition:opacity 1.2s ease, transform 6s linear;
  /* Muted and darkened: the photographs are atmosphere behind the seal, not
     the subject, and the gold aura has to stay readable over them. */
  filter:saturate(.72) brightness(.5);
}
.dswd-intro-frame.on{ opacity:1; transform:scale(1); }

/* A scrim over the photographs so the seal and wordmark keep their contrast
   whatever the image underneath happens to be. */
.dswd-intro::after{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:radial-gradient(120% 120% at 50% 45%,
             rgba(7,23,49,.55) 0%, rgba(7,23,49,.80) 55%, rgba(4,16,31,.94) 100%);
}
/* Everything above the scrim. */
.dswd-intro-glow{ z-index:2 !important; }
.dswd-intro-aura{ z-index:3 !important; }
.dswd-intro-seal{ z-index:4 !important; }
.dswd-glitter  { z-index:5 !important; }
.dswd-intro-word{ z-index:6 !important; }
.dswd-intro-skip{ z-index:7 !important; }

.dswd-intro-seal{
  position: relative;
  width: min(46vmin, 340px);
  height: min(46vmin, 340px);
  border-radius: 50%;
  z-index: 3;
  object-fit: cover;
  background: #fff;
  box-shadow: 0 0 0 6px rgba(252,209,22,.9),
              0 0 70px 18px rgba(252,209,22,.32),
              0 30px 90px rgba(0,0,0,.55);
  animation: introSeal 1.5s cubic-bezier(.2,.85,.25,1.03) both;
}
@keyframes introSeal{
  0%  { transform: scale(.55) rotate(-14deg); opacity: 0; filter: blur(6px); }
  55% { transform: scale(1.05) rotate(3deg);  opacity: 1; filter: blur(0); }
  100%{ transform: scale(1) rotate(0deg);     opacity: 1; }
}

/* The aura: three concentric rings breathing outward behind the seal. */
.dswd-intro-aura{
  position: absolute; top: 50%; left: 50%;
  width: min(46vmin, 340px); height: min(46vmin, 340px);
  margin: calc(min(46vmin, 340px) / -2) 0 0 calc(min(46vmin, 340px) / -2);
  border-radius: 50%;
  z-index: 1;
  pointer-events: none;
}
.dswd-intro-aura::before,
.dswd-intro-aura::after,
.dswd-intro-aura > span{
  content: ""; position: absolute; inset: 0;
  border-radius: 50%;
  border: 2px solid rgba(252,209,22,.5);
  animation: introAura 3.2s ease-out infinite;
}
.dswd-intro-aura::after{ animation-delay: 1.05s; border-color: rgba(109,213,166,.45); }
.dswd-intro-aura > span { animation-delay: 2.1s; border-color: rgba(255,255,255,.32); }
@keyframes introAura{
  0%  { transform: scale(1);   opacity: .8; }
  70% { opacity: .12; }
  100%{ transform: scale(2.1); opacity: 0; }
}

/* A soft glow disc under everything, so the seal sits in light rather than
   on a flat background. */
.dswd-intro-glow{
  position: absolute; top: 50%; left: 50%;
  width: min(80vmin, 620px); height: min(80vmin, 620px);
  margin: calc(min(80vmin, 620px) / -2) 0 0 calc(min(80vmin, 620px) / -2);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(252,209,22,.20) 0%, rgba(26,110,78,.13) 42%, transparent 68%);
  z-index: 0;
  animation: introGlow 3.4s ease-in-out infinite;
}
@keyframes introGlow{
  0%,100%{ transform: scale(1);    opacity: .85; }
  50%    { transform: scale(1.12); opacity: 1; }
}

/* Glitter: small four-pointed sparkles scattered around the seal. Positions
   and delays are set inline by the script so no two runs look identical. */
.dswd-glitter{
  position: absolute; z-index: 4; pointer-events: none;
  width: var(--g-size, 10px); height: var(--g-size, 10px);
  animation: introGlitter var(--g-dur, 2.2s) ease-in-out var(--g-delay, 0s) infinite;
  opacity: 0;
}
.dswd-glitter::before,
.dswd-glitter::after{
  content: ""; position: absolute; inset: 0;
  background: var(--g-color, #fcd116);
  /* A four-pointed star, which reads as a sparkle far better than a dot. */
  clip-path: polygon(50% 0%, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0% 50%, 39% 39%);
}
.dswd-glitter::after{ transform: rotate(45deg) scale(.6); opacity: .75; }
@keyframes introGlitter{
  0%   { opacity: 0; transform: scale(.2) rotate(0deg); }
  35%  { opacity: 1; transform: scale(1) rotate(70deg); }
  70%  { opacity: .85; transform: scale(.85) rotate(150deg); }
  100% { opacity: 0; transform: scale(.2) rotate(220deg); }
}

.dswd-intro-word{
  position: absolute; left: 0; right: 0;
  bottom: max(11vh, 84px);
  text-align: center; z-index: 5;
  color: #fff;
  opacity: 0; animation: introWord .8s .55s ease both;
}
.dswd-intro-word .t1{
  font-size: clamp(1.4rem, 4.5vw, 2.3rem); font-weight: 800; letter-spacing: -.01em;
  text-shadow: 0 2px 24px rgba(0,0,0,.5);
}
.dswd-intro-word .t1 .go{ color: #fcd116; }
.dswd-intro-word .t2{
  font-size: clamp(10.5px, 1.7vw, 13px); font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  opacity: .72; margin-top: 8px;
}
@keyframes introWord{ from{ opacity:0; transform: translateY(14px);} to{ opacity:1; transform:none; } }

.dswd-intro-skip{
  position: absolute; right: 20px; top: 20px; z-index: 6;
  background: rgba(255,255,255,.12); color: #fff;
  border: 1px solid rgba(255,255,255,.24); border-radius: 20px;
  padding: 8px 18px; font-size: 12.5px; font-weight: 700; cursor: pointer;
  min-height: 44px;
}
.dswd-intro-skip:hover{ background: rgba(255,255,255,.24); }

/* Nobody should be made to sit through an animation. */
@media (prefers-reduced-motion: reduce){
  .dswd-intro-seal, .dswd-intro-aura::before, .dswd-intro-aura::after,
  .dswd-intro-aura > span, .dswd-intro-glow, .dswd-glitter, .dswd-intro-word{
    animation: none !important;
    opacity: 1;
  }
  .dswd-glitter{ opacity: .8; }
}

/* High contrast strips decoration rather than fighting it. */
html.dswd-hc .dswd-intro{ background: #000 !important; }
html.dswd-hc .dswd-glitter,
html.dswd-hc .dswd-intro-aura,
html.dswd-hc .dswd-intro-glow{ display: none !important; }

/* ═══════════════════════════════════════════════════════════════════════
   HOMEPAGE SCROLL SCENES (assets/js/dswd-scroll-scenes.js)

   Both are injected only once their image has decoded, so a missing file
   leaves the section exactly as it was rather than showing an empty strip.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Ornamental bands, above and below Mission & Vision ─────────────────
   The artwork is a repeating border strip, so it tiles with repeat-x. The
   track is wider than the strip it sits in, which is what gives it room to
   travel without running out of pattern at either end. */
#mission-vision.has-bands{ position:relative; overflow:hidden; }
.dswd-band{
  position:absolute; left:0; right:0; height:74px;
  overflow:hidden; pointer-events:none; z-index:0;
}
.dswd-band--top{ top:0; }
.dswd-band--bottom{ bottom:0; }
.dswd-band-track{
  position:absolute; top:0; bottom:0; left:-40%; width:180%;
  background-repeat:repeat-x;
  background-position:center;
  background-size:auto 100%;
  will-change:transform;
  transition:transform .12s linear;
}
/* Faded into the section so the band reads as a border, not a photograph
   competing with the text beside it. */
.dswd-band::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(to bottom, rgba(255,255,255,.35) 0%, var(--surface-bg) 96%);
}
.dswd-band--bottom::after{
  background:linear-gradient(to top, rgba(255,255,255,.35) 0%, var(--surface-bg) 96%);
}
#mission-vision.has-bands > .container{ position:relative; z-index:1; }
#mission-vision.has-bands{ padding-top:112px; padding-bottom:112px; }

/* ── The handshake reassembling behind the programmes ───────────────────
   One image split down the middle. Each half is 50% of the box and shows its
   own side of the picture via background-size:200%, so when both sit at zero
   offset the halves abut and the handshake is whole again. */
.prog-overview.has-hands{ position:relative; overflow:hidden; }
.dswd-hands{
  position:absolute; top:50%; left:50%;
  width:min(78%, 900px);
  aspect-ratio:423 / 190;          /* the source artwork's own proportions */
  transform:translate(-50%,-50%);
  z-index:0; pointer-events:none;
  opacity:.13; transition:opacity .3s linear;
}
.dswd-hand{
  position:absolute; top:0; bottom:0; width:50%;
  background-repeat:no-repeat;
  background-size:200% 100%;       /* each half shows half the image */
  will-change:transform;
  transition:transform .12s linear;
}
.dswd-hand--left { left:0;  background-position:left center; }
.dswd-hand--right{ right:0; background-position:right center; }
.prog-overview.has-hands > .container{ position:relative; z-index:1; }

@media (max-width:768px){
  /* On a narrow screen the hands sit directly under the text; the bands just
     get shorter rather than dominating. */
  .dswd-hands{ display:none; }
  .dswd-band{ height:50px; }
  #mission-vision.has-bands{ padding-top:74px; padding-bottom:74px; }
}
@media (prefers-reduced-motion:reduce){
  .dswd-band-track, .dswd-hand{ transition:none; transform:none !important; }
  .dswd-hands{ display:none; }
}


/* ═══════════════════════════════════════════════════════════════════════
   HIGH CONTRAST — the surface layer's own opt-out

   dswd-public-enhance.css already forces a black/white/gold palette when
   high contrast is on, but this file loads after it and repaints every panel
   with the light surface. Rather than depend on !important arbitration
   between two stylesheets, the panel set states its own high-contrast values
   here, where it is the last word.
   ═══════════════════════════════════════════════════════════════════════ */
html.dswd-hc .panel,
html.dswd-hc .card,
html.dswd-hc .mod-card,
html.dswd-hc .card-citizen,
html.dswd-hc .sec-card,
html.dswd-hc .reg-card,
html.dswd-hc .kpi,
html.dswd-hc .stat-card,
html.dswd-hc .mod-stat-card,
html.dswd-hc .dswd-stat,
html.dswd-hc .dswd-card,
html.dswd-hc .svc-card,
html.dswd-hc .cs-card,
html.dswd-hc .album,
html.dswd-hc .event-block,
html.dswd-hc .dir-person,
html.dswd-hc .dd-card,
html.dswd-hc .dd-item,
html.dswd-hc .prog-cell,
html.dswd-hc .role-card,
html.dswd-hc .svc-facility,
html.dswd-hc .tp-item,
html.dswd-hc .news-card,
html.dswd-hc .panel-head,
html.dswd-hc .mod-card-header,
html.dswd-hc .ds-card{
  background: #000 !important;
  color: #fff !important;
  box-shadow: 0 0 0 2px #fcd116 !important;   /* the outline replaces elevation */
}

/* Messages keep their transparent treatment, but the semantic colour has to
   step up to something readable on black. */
html.dswd-hc .alert,
html.dswd-hc .dash-note,
html.dswd-hc .cms-note,
html.dswd-hc .svc-note,
html.dswd-hc .cs-note,
html.dswd-hc .ux-status{
  background: #000 !important;
  box-shadow: 0 0 0 2px currentColor !important;
}
html.dswd-hc .alert-success, html.dswd-hc .alert.ok,
html.dswd-hc .dash-note.ok{ color: #4ade80 !important; }
html.dswd-hc .alert-danger,  html.dswd-hc .alert.err{ color: #ff8579 !important; }
html.dswd-hc .alert-warning, html.dswd-hc .alert.warn,
html.dswd-hc .dash-note.warn{ color: #fcd116 !important; }
html.dswd-hc .alert-info,    html.dswd-hc .alert.info,
html.dswd-hc .dash-note.info{ color: #7dd3fc !important; }

/* ── The woven textile behind the featured programmes ──────────────────
   Cut into vertical slices that drift sideways together while alternate
   slices rise and fall, so the weave shears and re-knits as you scroll.
   Held well back in opacity — it is a backdrop for a list of programmes,
   not something to read through. */
.prog-highlight.has-ethnic{ position:relative; overflow:hidden; }
.dswd-ethnic{
  position:absolute; inset:-90px 0;    /* over-scan, so the vertical shear
                                          never exposes a bare edge */
  z-index:0; pointer-events:none;
  /* Raised from .085 — at that strength the textile was technically present
     and visually absent, which is not what "put it in the background" means.
     This is high enough to read as a woven backdrop while the wash below
     keeps the cards and body copy fully legible. */
  opacity:.30;
}
.dswd-ethnic-slice{
  position:absolute; top:0; bottom:0;
  background-repeat:repeat;
  background-size:auto 100%;
  will-change:transform;
  transition:transform .12s linear;
}
.prog-highlight.has-ethnic > .container{ position:relative; z-index:1; }
/* A wash over the top keeps the cards and body copy fully legible. Heavier in
   the middle, where the programme cards sit, and lighter at the edges so the
   pattern still shows as a border. */
.prog-highlight.has-ethnic::after{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:linear-gradient(180deg,
    rgba(255,255,255,.60) 0%,
    rgba(255,255,255,.88) 22%,
    rgba(255,255,255,.90) 78%,
    rgba(255,255,255,.60) 100%);
}
/* The cards sit on their own surface so nothing has to be read through the
   weave. */
.prog-highlight.has-ethnic .prog-row-item,
.prog-highlight.has-ethnic .card,
.prog-highlight.has-ethnic .panel{
  background:rgba(255,255,255,.96) !important;
  backdrop-filter:blur(2px);
}
@media (max-width:768px){
  /* Less of it on a phone, where the text sits directly over the pattern. */
  .dswd-ethnic{ opacity:.18; }
}
@media (prefers-reduced-motion:reduce){
  .dswd-ethnic-slice{ transition:none; transform:none !important; }
}
html.dswd-hc .dswd-ethnic{ display:none !important; }

/* ═══════════════════════════════════════════════════════════════════════
   CONFIRMATION PANEL (window.uxConfirm, assets/js/dswd-ux-rules.js)
   Replaces the browser's confirm() for destructive actions.
   ═══════════════════════════════════════════════════════════════════════ */
.ux-confirm{
  position:fixed; inset:0; z-index:3200;
  display:flex; align-items:center; justify-content:center; padding:22px;
  background:rgba(10,20,38,.62);
  opacity:0; visibility:hidden; transition:opacity .18s, visibility .18s;
}
.ux-confirm.show{ opacity:1; visibility:visible; }
.ux-confirm-box{
  background:#fff; border-radius:16px; padding:28px 30px 24px;
  width:min(440px,100%); text-align:center;
  box-shadow:0 24px 70px rgba(0,0,0,.4);
  transform:translateY(14px) scale(.97);
  transition:transform .2s cubic-bezier(.2,.9,.3,1.1);
}
.ux-confirm.show .ux-confirm-box{ transform:none; }
.ux-confirm-icon{
  width:62px; height:62px; border-radius:50%; margin:0 auto 16px;
  display:flex; align-items:center; justify-content:center;
  font-size:1.5rem; color:#c0392b; background:#fdecea;
}
.ux-confirm-title{ font-size:1.05rem; font-weight:800; color:#10141c; margin:0 0 8px; }
.ux-confirm-detail{ font-size:13.5px; color:#6b7789; line-height:1.7; margin:0 0 22px; text-align:center; }
.ux-confirm-actions{ display:flex; gap:10px; }
.ux-confirm-actions button{
  flex:1; border-radius:10px; padding:12px 18px;
  font-size:13.5px; font-weight:700; cursor:pointer; border:none; min-height:44px;
}
.ux-confirm-cancel{ background:#eef1f7; color:#3b4658; }
.ux-confirm-cancel:hover{ background:#e2e7f0; }
.ux-confirm-go{ background:#12386f; color:#fff; }
.ux-confirm-go:hover{ background:#0b2545; }
.ux-confirm-go.is-destructive{ background:#c0392b; }
.ux-confirm-go.is-destructive:hover{ background:#a5301f; }
/* A check-before-saving question (add / edit / update): blue, not red. */
.ux-confirm.is-safe .ux-confirm-icon{ color:#0038a8; background:#e8eefb; }
.ux-confirm-go:focus-visible, .ux-confirm-cancel:focus-visible{ outline:3px solid #fcd116; outline-offset:2px; }
.modal .ux-confirm{ z-index:3200; }
@media (prefers-reduced-motion:reduce){ .ux-confirm-box{ transition:none; } }
html.dswd-hc .ux-confirm-box{ background:#000 !important; box-shadow:0 0 0 2px #fcd116 !important; }

/* ═══════════════════════════════════════════════════════════════════════
   COLLAPSIBLE SIDEBAR  (assets/js/dswd-sidebar-collapse.js)

   Collapsed, the sidebar itself narrows to a column of icons. Three things
   the first attempt got wrong, all from assuming the three sidebars were
   built the same way:

     · The CMS links are `<a><i></i> Dashboard</a>` — the label is a bare text
       node, not a <span>. Hiding `> span` did nothing, so the text stayed and
       wrapped inside a 74px column. Bare text needs font-size:0 on the link,
       with the icon restored.

     · The staff sidebar has collapsible groups. Their heads carry an icon, a
       label and a caret, and their submenus stay open. Neither was handled,
       so a "collapsed" staff sidebar was a stack of half-cut group names.

     · Badges are numbers in a pill. At 74px they pushed the icon off-centre,
       so they become a dot in the corner instead.
   ═══════════════════════════════════════════════════════════════════════ */
:root{ --dswd-nav-mini: 76px; }

.dswd-collapse-btn{
  margin-left:auto; flex:0 0 auto;
  width:30px; height:30px; min-width:30px; min-height:30px; padding:0;
  border:none; border-radius:8px; cursor:pointer;
  background:rgba(255,255,255,.10); color:rgba(255,255,255,.8);
  display:flex; align-items:center; justify-content:center; font-size:.72rem;
  transition:background .18s, color .18s;
}
.dswd-collapse-btn:hover{ background:rgba(255,255,255,.22); color:#fff; }

/* ── The bar and the content beside it ────────────────────────────────── */
html.dswd-nav-collapsed .dswd-sidebar,
html.dswd-nav-collapsed .citizen-sidebar,
html.dswd-nav-collapsed .mod-sidebar{
  width:var(--dswd-nav-mini) !important;
  min-width:var(--dswd-nav-mini) !important;
  overflow-x:hidden;
  transition:width .22s ease;
}
html.dswd-nav-collapsed .main-wrap,
html.dswd-nav-collapsed .main-content,
html.dswd-nav-collapsed .content-wrap,
html.dswd-nav-collapsed .citizen-main,
html.dswd-nav-collapsed .mod-main,
html.dswd-nav-collapsed .mod-content{
  margin-left:var(--dswd-nav-mini) !important;
  transition:margin-left .22s ease;
}

/* ── Everything that is only meaningful with room for words ──────────── */
html.dswd-nav-collapsed .dswd-sidebar .nav-section,
html.dswd-nav-collapsed .citizen-sidebar .cz-section,
html.dswd-nav-collapsed .mod-sidebar .mod-nav-section,
html.dswd-nav-collapsed .dswd-sb-search,
html.dswd-nav-collapsed .cz-search,
html.dswd-nav-collapsed .mod-search,
html.dswd-nav-collapsed .cz-hotline,
html.dswd-nav-collapsed .cz-progs,
html.dswd-nav-collapsed .cz-progs-label,
html.dswd-nav-collapsed .dswd-brand-meta,
html.dswd-nav-collapsed .cz-brand-meta,
html.dswd-nav-collapsed .mod-brand-meta,
html.dswd-nav-collapsed .cz-u-name,
html.dswd-nav-collapsed .cz-u-role,
html.dswd-nav-collapsed .cz-u-org,
html.dswd-nav-collapsed .mod-profile-meta,
html.dswd-nav-collapsed .dswd-sub,
html.dswd-nav-collapsed .caret{
  display:none !important;
}

/* ── Links become centred icons ──────────────────────────────────────── */
html.dswd-nav-collapsed .dswd-link,
html.dswd-nav-collapsed .dswd-grouphead,
html.dswd-nav-collapsed .cz-link,
html.dswd-nav-collapsed .mod-nav-item{
  justify-content:center;
  gap:0;
  padding-left:0 !important;
  padding-right:0 !important;
  position:relative;
  /* Collapses any bare text node — the CMS links have no span to hide. */
  font-size:0 !important;
}

/* The icon is restored to a readable size, since font-size:0 above hides
   everything indiscriminately. */
html.dswd-nav-collapsed .dswd-link > i,
html.dswd-nav-collapsed .dswd-link .nav-icon,
html.dswd-nav-collapsed .dswd-grouphead > i,
html.dswd-nav-collapsed .dswd-grouphead .nav-icon,
html.dswd-nav-collapsed .cz-link > i,
html.dswd-nav-collapsed .cz-link .cz-icon,
html.dswd-nav-collapsed .mod-nav-item > i{
  font-size:1.02rem !important;
  width:auto !important;
  margin:0 !important;
}

/* Labels stay in the DOM for screen readers rather than being removed. */
html.dswd-nav-collapsed .dswd-link > span:not(.nav-badge),
html.dswd-nav-collapsed .dswd-grouphead > span:not(.nav-badge),
html.dswd-nav-collapsed .cz-link > span:not(.cz-indicator),
html.dswd-nav-collapsed .mod-nav-item > span{
  position:absolute !important; width:1px; height:1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap;
}

/* A count would shove the icon off-centre, so it becomes a dot. */
html.dswd-nav-collapsed .nav-badge{
  position:absolute; top:7px; right:14px;
  width:8px; height:8px; min-width:8px; padding:0;
  border-radius:50%; font-size:0 !important;
  background:#ce1126; color:transparent;
  box-shadow:0 0 0 2px rgba(11,37,69,.9);
}

/* ── Brand, user box, sign-out ────────────────────────────────────────── */
html.dswd-nav-collapsed .dswd-brand,
html.dswd-nav-collapsed .cz-brand,
html.dswd-nav-collapsed .mod-brand{
  justify-content:center; padding-left:0; padding-right:0; gap:0;
}
html.dswd-nav-collapsed .dswd-collapse-btn{
  margin-left:0; position:absolute; top:10px; right:10px;
  width:24px; height:24px; min-width:24px; min-height:24px; font-size:.6rem;
}
html.dswd-nav-collapsed .dswd-brand,
html.dswd-nav-collapsed .cz-brand,
html.dswd-nav-collapsed .mod-brand{ position:relative; padding-top:34px; }

html.dswd-nav-collapsed .cz-user-row,
html.dswd-nav-collapsed .mod-profile{ justify-content:center; }
html.dswd-nav-collapsed .cz-logout,
html.dswd-nav-collapsed .mod-logout{
  font-size:0 !important; justify-content:center; padding-left:0; padding-right:0;
}
html.dswd-nav-collapsed .cz-logout i,
html.dswd-nav-collapsed .mod-logout i{ font-size:.9rem !important; }

/* ── Hover slides the labels back, without leaving collapsed state ────── */
@media (hover:hover) and (min-width:993px){
  html.dswd-nav-collapsed .dswd-sidebar:hover,
  html.dswd-nav-collapsed .citizen-sidebar:hover,
  html.dswd-nav-collapsed .mod-sidebar:hover{
    width:var(--sidebar-w,288px) !important;
    min-width:var(--sidebar-w,288px) !important;
    box-shadow:8px 0 40px rgba(0,15,46,.45);
    z-index:1060;
  }
  html.dswd-nav-collapsed .dswd-sidebar:hover .nav-section,
  html.dswd-nav-collapsed .citizen-sidebar:hover .cz-section,
  html.dswd-nav-collapsed .mod-sidebar:hover .mod-nav-section,
  html.dswd-nav-collapsed .dswd-sidebar:hover .dswd-brand-meta,
  html.dswd-nav-collapsed .citizen-sidebar:hover .cz-brand-meta,
  html.dswd-nav-collapsed .citizen-sidebar:hover .cz-u-name,
  html.dswd-nav-collapsed .citizen-sidebar:hover .cz-u-role,
  html.dswd-nav-collapsed .dswd-sidebar:hover .caret{
    display:block !important;
  }
  html.dswd-nav-collapsed .dswd-sidebar:hover .dswd-link,
  html.dswd-nav-collapsed .dswd-sidebar:hover .dswd-grouphead,
  html.dswd-nav-collapsed .citizen-sidebar:hover .cz-link,
  html.dswd-nav-collapsed .mod-sidebar:hover .mod-nav-item{
    justify-content:flex-start; gap:11px;
    padding-left:18px !important; padding-right:18px !important;
    font-size:13px !important;
  }
  html.dswd-nav-collapsed .dswd-sidebar:hover .dswd-link > span,
  html.dswd-nav-collapsed .dswd-sidebar:hover .dswd-grouphead > span,
  html.dswd-nav-collapsed .citizen-sidebar:hover .cz-link > span,
  html.dswd-nav-collapsed .mod-sidebar:hover .mod-nav-item > span{
    position:static !important; width:auto; height:auto; clip:auto;
  }
  html.dswd-nav-collapsed .dswd-sidebar:hover .nav-badge{
    position:static; width:auto; height:auto; min-width:20px;
    padding:2px 7px; border-radius:20px; font-size:10.5px !important;
    color:#fff; box-shadow:none;
  }
  html.dswd-nav-collapsed .citizen-sidebar:hover .cz-logout,
  html.dswd-nav-collapsed .mod-sidebar:hover .mod-logout{ font-size:.76rem !important; }
  html.dswd-nav-collapsed .dswd-sidebar:hover .dswd-collapse-btn,
  html.dswd-nav-collapsed .citizen-sidebar:hover .dswd-collapse-btn,
  html.dswd-nav-collapsed .mod-sidebar:hover .dswd-collapse-btn{
    position:static; width:30px; height:30px; min-width:30px; min-height:30px;
    font-size:.72rem; margin-left:auto;
  }
}

/* Below the tablet breakpoint the sidebar is a drawer; collapsing is moot. */
@media (max-width:992px){
  .dswd-collapse-btn{ display:none !important; }
  html.dswd-nav-collapsed .dswd-sidebar,
  html.dswd-nav-collapsed .citizen-sidebar,
  html.dswd-nav-collapsed .mod-sidebar{ width:var(--sidebar-w,288px) !important; }
  html.dswd-nav-collapsed .main-wrap,
  html.dswd-nav-collapsed .main-content,
  html.dswd-nav-collapsed .citizen-main,
  html.dswd-nav-collapsed .mod-main{ margin-left:0 !important; }
}
@media print{ .dswd-collapse-btn{ display:none !important; } }

/* ═══════════════════════════════════════════════════════════════════════
   DRAG-TO-REORDER  (assets/js/dswd-reorder.js)
   Replaces the "Sort Order" number field on the CMS lists.
   ═══════════════════════════════════════════════════════════════════════ */
[data-reorder] tr{ cursor:grab; transition:background .15s, opacity .15s; }
[data-reorder] tr:active{ cursor:grabbing; }
[data-reorder] tr.is-dragging{ opacity:.45; background:#eef3fb; }
[data-reorder] tr.is-over{ box-shadow:inset 0 2px 0 #12386f; }

.reorder-handle{
  display:inline-flex; align-items:center; gap:7px;
  color:#94a3b8; font-weight:700; font-size:12.5px;
  padding:4px 6px; border-radius:6px; cursor:grab; user-select:none;
}
.reorder-handle:hover{ background:#eef3fb; color:#12386f; }
.reorder-handle:focus-visible{ outline:3px solid #12386f; outline-offset:2px; color:#12386f; }
.reorder-handle i{ font-size:.8rem; }

/* Saving feedback, so a drop that failed is not mistaken for one that worked. */
.reorder-status{
  position:fixed; left:50%; bottom:24px; transform:translateX(-50%) translateY(12px);
  background:#0b2545; color:#fff; font-size:12.5px; font-weight:700;
  padding:11px 20px; border-radius:999px; z-index:3100;
  box-shadow:0 12px 34px rgba(0,0,0,.3);
  opacity:0; visibility:hidden; transition:opacity .2s, transform .2s, visibility .2s;
}
.reorder-status.show{ opacity:1; visibility:visible; transform:translateX(-50%); }
.reorder-status.ok{ background:#15803d; }
.reorder-status.err{ background:#c0392b; }
@media (max-width:768px){ [data-reorder] tr{ cursor:default; } }

/* ═══════════════════════════════════════════════════════════════════════
   PHONE CAPTURE HANDOFF  (citizen/assets/js/phone-handoff.js)
   ═══════════════════════════════════════════════════════════════════════ */
.ph-overlay{
  position:fixed; inset:0; z-index:3400;
  display:flex; align-items:center; justify-content:center; padding:22px;
  background:rgba(10,20,38,.68);
  opacity:0; visibility:hidden; transition:opacity .2s, visibility .2s;
}
.ph-overlay.show{ opacity:1; visibility:visible; }
.ph-box{
  background:#fff; border-radius:18px; padding:30px 32px 26px;
  width:min(430px,100%); text-align:center; position:relative;
  box-shadow:0 26px 70px rgba(0,0,0,.42);
  max-height:92vh; overflow-y:auto;
}
.ph-close{
  position:absolute; top:12px; right:14px;
  width:34px; height:34px; min-width:34px; min-height:34px; padding:0;
  border:none; background:#eef1f7; color:#3b4658;
  border-radius:50%; font-size:20px; line-height:1; cursor:pointer;
}
.ph-close:hover{ background:#e2e7f0; }
.ph-title{ font-size:1.12rem; font-weight:800; color:#10141c; margin:0 0 8px; }
.ph-sub{ font-size:13px; color:#6b7789; line-height:1.7; margin:0 0 20px; text-align:center; }

.ph-qr{
  display:flex; align-items:center; justify-content:center;
  min-height:210px; padding:14px; margin-bottom:18px;
  background:#fff; border-radius:12px; box-shadow:inset 0 0 0 1px #e3e9f1;
}
.ph-qr img, .ph-qr canvas{ display:block; }
.ph-qr-missing{ color:#6b7789; font-size:12.5px; line-height:1.7; padding:18px; }
.ph-qr-missing i{ display:block; font-size:2rem; opacity:.3; margin-bottom:10px; }

.ph-link{ margin-bottom:18px; }
.ph-link-label{ display:block; font-size:11px; color:#8896a8; margin-bottom:6px; }
.ph-link code{
  display:block; font-size:11.5px; color:#12386f; background:#f4f7fb;
  border-radius:8px; padding:10px 12px; word-break:break-all; line-height:1.6;
}

.ph-state{
  display:flex; align-items:center; justify-content:center; gap:10px;
  font-size:13px; font-weight:700; color:#12386f;
  background:#eef3fb; border-radius:10px; padding:13px 16px;
}
.ph-state.is-ok  { color:#15803d; background:#eefaf2; }
.ph-state.is-err { color:#c0392b; background:#fdecea; }
.ph-state.is-warn{ color:#b45309; background:#fff6e0; }

.ph-expiry{ font-size:11.5px; color:#8896a8; margin-top:12px; }

@media (prefers-reduced-motion:reduce){ .ph-overlay{ transition:none; } }
html.dswd-hc .ph-box{ background:#000 !important; box-shadow:0 0 0 2px #fcd116 !important; }
html.dswd-hc .ph-qr{ background:#fff !important; }
