/*
 * Charity Association Pro 2026 — the public site.
 *
 * Every colour, radius, shadow, border weight, spacing scale and font name in
 * here is read from a custom property. The values themselves are declared in
 * one place — app/Support/SiteTheme.php — and arrive in a small block in the
 * page's head. Not one rule below holds a colour of its own, and a guard fails
 * if one ever does; the sole exception is print, which ignores the theme by
 * rule: black on white, always.
 *
 * The control panel is dark and stays dark; the theme belongs to this site
 * alone. Right to left, fixed. Every font file is served from this project;
 * nothing is fetched from the internet while the site is running — the active
 * font's two faces are declared in the same block in the head, and the other
 * fourteen fonts stay on disk unloaded.
 */

/* The numbers' font. The Arabic font changes with the theme; this one does
   not — its figures share one width, so a column of them lines up under
   itself. */
@font-face {
    font-family: 'Inter';
    src: url('/fonts/inter/inter_regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Inter';
    src: url('/fonts/inter/inter_bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

:root {
    /* Layout, not theme: how wide a comfortable line of reading is. */
    --reading-width: 44rem;
}

* {
    box-sizing: border-box;
}

html {
    /* Numerals keep a fixed width wherever they appear, so a column of them
       lines up under itself. */
    font-variant-numeric: tabular-nums;
}

/* The page fills the window even when it has little in it, so the footer sits
   at the bottom of the screen instead of hanging in the middle of it with
   emptiness underneath.

   The decoration — when one is switched on — is painted here, under the whole
   page: a repeating tile carried inside the stylesheet, never a file that
   loads. With none chosen the image is simply none. */
body {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background-color: var(--page);
    background-image: var(--decoration-image);
    color: var(--text);
    font-family: var(--font-family);
    font-size: calc(1.0625rem * var(--font-scale));
    line-height: 1.9;
}

/* A number inside Arabic text is isolated, so its digits cannot be reordered by
   what sits beside them. */
/* م-٢٦ · the same three rules the panel's numerals have had since the start.
   `tnum` makes every digit the same width, so a column of amounts lines up on
   its units instead of wandering; `direction: ltr` makes a number read left to
   right inside an Arabic sentence — «١٢٣٤٥» is not «٥٤٣٢١» — and `isolate`
   keeps it from dragging the sentence around it. A donor reading a total is the
   one reader who cannot be asked to guess. */
.number {
    font-family: 'Inter', system-ui, sans-serif;
    font-feature-settings: 'tnum' 1;
    unicode-bidi: isolate;
    direction: ltr;
}

.page {
    /* Takes whatever room is left over, which is what pushes the footer down. */
    flex: 1 0 auto;
    width: 100%;
    max-width: 68rem;
    margin: 0 auto;
    padding: calc(2.5rem * var(--space)) 1.25rem calc(4rem * var(--space));
}

/* =====================================================================
   The header and the footer.

   Not one line of script anywhere in here. The menu that opens on a phone,
   the drop-downs and the button held in the corner of the window are the
   browser's own elements and these rules — nothing waits for anything to
   load, and nothing stops working when scripting is switched off.
   ===================================================================== */

/* The header paints no background of its own, so the page — and the
   decoration on it — runs behind it. It stands above the occasion symbol
   hanging under its edge, which is why it carries a stacking order. */
.site-header {
    position: relative;
    z-index: 20;
    border-bottom: var(--border-width) solid var(--line);
}

.site-header__inner {
    max-width: 68rem;
    margin: 0 auto;
    padding: 0 1.25rem;
    display: flex;
    align-items: center;
    gap: 1.5rem;
}

.site-header__strip {
    border-bottom: var(--border-width) solid var(--line);
    background: var(--surface);
}

.site-header__strip .site-header__inner {
    min-height: 36px;
    justify-content: space-between;
    font-size: 0.92rem;
}

.site-header__main .site-header__inner {
    min-height: 80px;
}

.site-header__logo {
    display: block;
    height: 40px;
    max-width: 200px;
    width: auto;
    object-fit: contain;
}

/* No logo chosen is not an empty space: the name stands where the picture
   would be. */
.site-header__name {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--headings);
}

.site-header__side {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-inline-start: auto;
}

.site-header__phone {
    color: var(--text);
    text-decoration: none;
}

/* It was a word that did nothing until the basket was built. It is the link it
   always named now, and it carries the count of projects in the basket — never
   of lines, and never a nought.

   The mark, the word, the number — in that order, which in a page read from the
   right is the order the eye meets them. The mark is the system's own drawing
   and follows no field: it is what the eye finds before it reads. */
.site-header__cart {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.9rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    color: var(--text-quiet);
    text-decoration: none;
}

.site-header__cart-mark {
    display: inline-flex;
    flex: none;
}

.site-header__cart-mark svg {
    width: 1.25rem;
    height: 1.25rem;
}

.site-header__cart-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.4rem;
    padding: 0 0.35rem;
    border-radius: var(--radius);
    background: var(--primary);
    color: var(--on-primary);
    font-size: 0.85rem;
    font-weight: 700;
}

/* Two menus and one of them is ever in the page. On a wide screen the list
   stands open; on a phone it opens from the side. The other is removed by
   display:none, which takes it out of the page for a screen reader too, so
   nobody meets the same menu twice. */
.site-header__menu {
    display: none;
}

.site-header__inside-menu {
    display: none;
}

/* ---------- the five shapes of the header ---------- */

/* One: the links take the room between the logo and the far side, and stand
   in the middle of it. */
.site-header--1 .site-header__links {
    flex: 1;
    display: flex;
    justify-content: center;
}

/* Two: the logo in the middle of its own line with the basket at the end of
   it, and the links on a line of their own underneath. */
.site-header--2 .site-header__main .site-header__inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    grid-template-areas: "blank brand side" "menu menu menu";
    row-gap: 0.6rem;
    padding-block: 0.9rem;
}

.site-header--2 .site-header__brand {
    grid-area: brand;
    justify-self: center;
}

.site-header--2 .site-header__side {
    grid-area: side;
    justify-self: end;
    margin-inline-start: 0;
}

.site-header--2 .site-header__links {
    grid-area: menu;
    justify-self: center;
}

/* Three: a thin strip above, and under it the same arrangement as one. */
.site-header--3 .site-header__links {
    flex: 1;
    display: flex;
    justify-content: center;
}

/* Four: the logo and the basket on one line, and the links on a line of
   their own across the whole width. This is the one shape whose alignment is
   the owner's to choose. */
.site-header--4 .site-header__main .site-header__inner {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas: "brand side" "menu menu";
    row-gap: 0.6rem;
    padding-block: 0.9rem;
}

.site-header--4 .site-header__side {
    justify-self: end;
    margin-inline-start: 0;
}

.site-header--4 .site-header__links {
    grid-area: menu;
    display: flex;
}

.site-header--4.site-header--align-right .site-header__links {
    justify-content: flex-start;
}

.site-header--4.site-header--align-centre .site-header__links {
    justify-content: center;
}

/* Five: everything pressed together, and the thinnest of the five. */
.site-header--5 .site-header__main .site-header__inner {
    min-height: 56px;
    gap: 1rem;
}

.site-header--5 .site-header__logo {
    height: 34px;
}

/* ---------- a list of links, in the header and in the footer ---------- */

.menu-list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 1.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.menu-list__link {
    display: inline-block;
    padding: 0.4rem 0.2rem;
    color: var(--text);
    text-decoration: none;
}

.menu-list--plain .menu-list__link--current {
    box-shadow: inset 0 -2px 0 var(--primary);
    color: var(--headings);
}

.menu-list--card .menu-list__link {
    padding: 0.45rem 0.9rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--page);
    box-shadow: var(--shadow);
    transition: transform var(--transition), box-shadow var(--transition);
}

.menu-list--card .menu-list__link:hover {
    transform: var(--hover-transform);
    box-shadow: var(--hover-shadow);
}

.menu-list--card .menu-list__link--current {
    border-color: var(--primary);
    color: var(--headings);
}

/* A drop-down out of the browser's own element. It opens on a click, on a
   computer and on a phone alike.
   What that costs: it stays open until it is clicked again or until the page
   changes. Closing it by clicking elsewhere needs a script. */
.menu-list__drop {
    position: relative;
}

.menu-list__drop > summary {
    list-style: none;
    cursor: pointer;
}

.menu-list__drop > summary::-webkit-details-marker {
    display: none;
}

.menu-list__drop > summary::after {
    content: '▾';
    margin-inline-start: 0.3rem;
    color: var(--text-quiet);
}

.menu-list__children {
    position: absolute;
    top: 100%;
    inset-inline-start: 0;
    min-width: 12rem;
    margin: 0.3rem 0 0;
    padding: 0.35rem;
    list-style: none;
    background: var(--page);
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-pop);
    z-index: 20;
}

.menu-list__children .menu-list__link {
    display: block;
    padding: 0.4rem 0.6rem;
}

/* Inside «عرض الكل»: a row that stood on the line and carried a list of its
   own keeps it, laid out in place. Not a second drop-down inside the first —
   one click reaches anything, and the list is static so it does not float away
   from the box it belongs to. */
.menu-list__gathered-name {
    display: block;
    padding: 0.4rem 0.6rem;
    color: var(--text-quiet);
}

.menu-list__gathered {
    position: static;
    margin: 0;
    padding: 0;
    padding-inline-start: 0.8rem;
    list-style: none;
}

/* ---------- the social accounts ---------- */

.socials {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.socials__link {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: var(--border-width) solid var(--line);
    border-radius: 50%;
    color: var(--text);
}

.socials__link svg {
    width: 1.05rem;
    height: 1.05rem;
}

/* ---------- the tally bar ---------- */

/* Still in its place in every shape: no movement, no marquee, no scrolling
   text. And every word and digit in it was typed by hand. */
.tally-bar {
    background: var(--surface);
    border-bottom: var(--border-width) solid var(--line);
}

.tally-bar__inner {
    max-width: 68rem;
    margin: 0 auto;
    padding: 0.35rem 1.25rem;
    min-height: 40px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.9rem;
}

.tally-bar__title {
    color: var(--text-quiet);
    font-size: 0.95rem;
}

.tally-bar__amount {
    font-weight: 700;
}

/* One: a tidy line — small writing, the number standing out, an upright rule,
   then the number of givers. */
.tally-bar--1 .tally-bar__amount {
    font-size: 1.35rem;
    line-height: 1.4;
}

.tally-bar--1 .tally-bar__count {
    padding-inline-start: 0.9rem;
    border-inline-start: var(--border-width) solid var(--line);
}

.tally-bar__count {
    color: var(--text-quiet);
}

/* Two: three boxes, each a number over its own name. */
.tally-bar--2 .tally-bar__inner {
    justify-content: center;
    gap: 0 2.5rem;
    padding-block: 0.6rem;
}

.tally-bar__cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.5;
    padding-inline: 1.25rem;
    border-inline-start: var(--border-width) solid var(--line);
}

.tally-bar__cell:last-child {
    border-inline-start: 0;
}

.tally-bar__cell-value {
    font-size: 1.3rem;
    font-weight: 700;
}

.tally-bar__cell-label {
    color: var(--text-quiet);
    font-size: 0.9rem;
}

/* Three: a bar of how far along a target it is. */
.tally-bar--3 .tally-bar__inner {
    display: block;
    padding-block: 0.55rem;
}

.tally-bar__progress-line {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.9rem;
}

.tally-bar__target {
    color: var(--text-quiet);
}

.tally-bar__track {
    height: 8px;
    margin-top: 0.4rem;
    border-radius: 999px;
    background: var(--line);
    overflow: hidden;
}

/* It fills from the reading side, and it never passes its own end: the width
   handed to it is capped at a hundred before it reaches here. */
.tally-bar__fill {
    display: block;
    height: 100%;
    max-width: 100%;
    border-radius: 999px;
    background: var(--primary);
}

/* Four: one very large number, with the small writing above and below it. */
.tally-bar--4 .tally-bar__inner {
    justify-content: center;
    padding-block: 0.7rem;
}

.tally-bar__stack {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.4;
}

.tally-bar--4 .tally-bar__amount {
    font-size: 2rem;
    line-height: 1.3;
}

/* Five: a strip that sets it apart from the header, and the number in a
   colour of its own. On a light palette the strip is the deep heading colour;
   on a dark one it is the raised surface — both come finished from the one
   central place. */
.tally-bar--5 {
    background: var(--strip);
    border-bottom: 0;
}

.tally-bar--5 .tally-bar__inner {
    justify-content: center;
}

.tally-bar--5 .tally-bar__title,
.tally-bar--5 .tally-bar__count {
    color: var(--on-strip-quiet);
}

.tally-bar--5 .tally-bar__amount {
    color: var(--strip-accent);
    font-size: 1.35rem;
}

/* ---------- the occasion symbol ---------- */

/* A small shape hanging on a thread from the header's lower edge — from under
   the last strip when a tally bar is drawn, because the well stands after
   whatever the top of the page carries. On the reading side's far edge, away
   from the logo, which stays the first thing the eye lands on.

   It drops once when the page opens and then stands still: the well clips the
   fall, the animation runs a single time, and nothing sways or loops. The
   drop-down menus stand above it always — the header's stacking order sees to
   that — and a narrow phone does not draw it at all. */
.occasion-well {
    position: relative;
    z-index: 10;
    pointer-events: none;
}

.occasion {
    position: absolute;
    top: 0;
    left: clamp(1.25rem, 7vw, 5rem);
    display: flex;
    flex-direction: column;
    align-items: center;
    color: var(--occasion-colour);
    animation: occasion-drop 0.9s cubic-bezier(0.22, 1.2, 0.4, 1) both;
}

.occasion__thread {
    width: 2px;
    height: 52px;
    background: currentColor;
    opacity: 0.5;
}

.occasion__symbol {
    display: block;
}

.occasion__symbol svg {
    display: block;
    width: 46px;
    height: 46px;
}

@keyframes occasion-drop {
    from {
        transform: translateY(-105%);
    }

    to {
        transform: translateY(0);
    }
}

/* The mourning ribbon is the exception written into the brief: it never takes
   the theme's colour — its own comes fixed from the central place — and it
   never moves. */
.occasion--mourning {
    animation: none;
}

/* ---------- the button held in the corner ---------- */

/* Held there by this rule and nothing else: no scroll is measured and no
   script runs. */
.whatsapp-float {
    position: fixed;
    bottom: 1.25rem;
    left: 1.25rem;
    z-index: 50;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3.25rem;
    height: 3.25rem;
    border-radius: 50%;
    background: var(--primary);
    color: var(--on-primary);
    box-shadow: var(--shadow-pop);
}

.whatsapp-float svg {
    width: 1.6rem;
    height: 1.6rem;
}

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

.site-footer {
    margin-top: calc(4rem * var(--space));
    border-top: var(--border-width) solid var(--line);
    background: var(--surface);
}

.site-footer__inner {
    max-width: 68rem;
    margin: 0 auto;
    padding: calc(40px * var(--space)) 1.25rem;
    display: grid;
    gap: 2rem;
    align-items: start;
}

/* The columns are counted from what is actually there. A column with nothing
   in it is never drawn, and the ones beside it spread into its room. */
.site-footer--1 .site-footer__inner,
.site-footer--2 .site-footer__inner,
.site-footer--5 .site-footer__inner {
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
}

.site-footer--2 .site-footer__column--brand {
    grid-row: 1;
}

.site-footer--3 .site-footer__inner {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
}

/* Four: one bar, and everything stands in it — the bottom line included, or
   it would be two bars. */
.site-footer--4 .site-footer__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.25rem 2rem;
    min-height: 56px;
    padding-block: 0.5rem;
}

.site-footer__logo {
    display: block;
    height: 32px;
    max-width: 160px;
    width: auto;
    object-fit: contain;
}

.site-footer__name {
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--headings);
}

.site-footer__about {
    margin: 0.75rem 0 0;
    color: var(--text-quiet);
    max-width: 28rem;
}

.site-footer__title {
    margin: 0 0 0.75rem;
    font-size: 1rem;
    font-weight: 700;
    color: var(--headings);
}

.site-footer__column .menu-list {
    flex-direction: column;
    align-items: stretch;
    gap: 0.15rem;
}

.site-footer--3 .site-footer__column .menu-list,
.site-footer--4 .site-footer__column .menu-list {
    flex-direction: row;
    align-items: center;
    gap: 0.3rem 1.25rem;
}

.site-footer--3 .site-footer__column .menu-list {
    justify-content: center;
}

/* A long column of links beside short columns leaves a hole under them and
   stretches the footer for nothing. Past a certain number it runs in two
   columns inside its own place, which is what the two-column shape does by
   hand. */
.site-footer__column .menu-list--split {
    display: block;
    column-count: 2;
    column-gap: 1.5rem;
}

.site-footer__column .menu-list--split .menu-list__item {
    break-inside: avoid;
}

.site-footer__contact {
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--text-quiet);
}

.site-footer__contact li {
    margin-bottom: 0.4rem;
}

.site-footer__contact a {
    color: inherit;
}

/* The closing line stands in a bar of its own across the whole width, with a
   rule above it, in all five shapes — it is the line that closes the site, not
   a tail on the first column. */
.site-footer__bottom {
    border-top: var(--border-width) solid var(--line);
}

.site-footer__inner--bottom {
    display: block;
    padding-block: 1rem;
}

/* Three tracks and the rights in the middle one, so they sit in the middle of
   the page itself — not in the middle of what is left over beside the
   accounts. */
.site-footer__bottom-inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 0.75rem 1.5rem;
}

.site-footer__bottom-side {
    display: flex;
    align-items: center;
}

.site-footer__bottom-side--end {
    justify-content: flex-end;
}

.site-footer__copyright {
    margin: 0;
    text-align: center;
    color: var(--text-quiet);
    font-size: 0.95rem;
}

.site-footer__licence {
    color: var(--text-quiet);
}

/* Five: a strip of its own along the bottom, set apart from the rest. */
.site-footer--5 .site-footer__bottom {
    border-top: 0;
    background: var(--strip);
    color: var(--on-strip);
}

.site-footer--5 .site-footer__inner--bottom {
    min-height: 48px;
    padding-block: 0.6rem;
}

.site-footer--5 .site-footer__copyright {
    color: var(--on-strip-quiet);
}

.site-footer--5 .site-footer__bottom .socials__link {
    color: var(--on-strip);
    border-color: var(--strip-line);
}

.page__title {
    margin: 0 0 2rem;
    font-size: 2rem;
    line-height: 1.5;
    font-weight: 700;
    color: var(--headings);
}

/* The heading of an error page is a whole sentence rather than a title, because
   the owner writes one text per page and the page says it (ع-٢). Two lines of a
   sentence set at 2rem read as shouting at somebody who has just been refused
   or has just lost a form; this keeps the weight and the place of a heading and
   drops the volume. */
.page__title--sentence {
    max-width: 40rem;
    font-size: 1.35rem;
    line-height: 1.9;
}

.page__image {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius);
}

.page__image-figure {
    margin: 0 0 2rem;
}

.page__image-figure--tail {
    margin: 2.5rem 0 0;
}

.section {
    margin: 0 0 calc(2rem * var(--space));
    max-width: var(--reading-width);
}

.section__heading {
    margin: 0 0 0.6rem;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--headings);
}

.section__body {
    margin: 0;
    white-space: pre-line;
}

/* Form four and form five run the paragraphs together as one piece of writing,
   with no headings and no gaps that read as a break. */
.prose {
    max-width: var(--reading-width);
}

.prose p {
    margin: 0 0 1.2rem;
    white-space: pre-line;
}

/* Form three: the image beside the first paragraph, and everything after it
   across the full width.

   The plan puts the image on the left and the writing on its right, so the
   columns are placed by hand rather than taken in the order they are written:
   the image stays first in the writing, so a phone — which has one column —
   still leads with the picture. */
.beside {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
    margin: 0 0 2rem;
}

.beside__image {
    grid-column: 2;
    grid-row: 1;
}

.beside__text {
    grid-column: 1;
    grid-row: 1;
}

.beside .section {
    margin: 0;
}

/* ---------- entries shared by several kinds ---------- */

.entry__title {
    margin: 0 0 0.35rem;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--headings);
}

.entry__title a {
    color: inherit;
}

.entry__note {
    margin: 0 0 0.5rem;
    color: var(--text-quiet);
}

.file-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0.6rem 0 0;
}

.file-button {
    display: inline-flex;
    align-items: center;
    padding: 0.4rem 0.9rem;
    border: var(--border-width) solid var(--primary);
    border-radius: var(--radius);
    background: var(--primary);
    color: var(--on-primary);
    text-decoration: none;
    font: inherit;
    cursor: pointer;
}

.file-button--quiet {
    background: none;
    color: var(--text);
    border-color: var(--line-strong);
}

.rows {
    display: flex;
    flex-direction: column;
    gap: calc(1.25rem * var(--space));
}

.row-item {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: 1rem;
    align-items: start;
    padding-bottom: calc(1.25rem * var(--space));
    border-bottom: var(--border-width) solid var(--line);
}

.row-item__year {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--headings);
}

.row-item__thumb {
    display: block;
    width: 6rem;
}

/* Three in a row, counted and not fitted. Letting the browser fit as many as
   the width allows put four in a row, and four columns are too narrow for the
   titles this site carries. */
.cards {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: calc(1.5rem * var(--space));
}

/* The movement on hover is a value from the shape set — none, a small lift or
   a small growth — and it stops for anyone whose device asks for less motion. */
.card-item {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    transition: transform var(--transition);
}

.card-item:hover {
    transform: var(--hover-transform);
}

/* ب-٤/١ · الشريطُ الجانبيّ — تركيبةُ «بحدٍّ جانبيّ» وحدَها ترفع عرضَه.

   🔑 **القاعدةُ مرسومةٌ دائمًا وعرضُها صفرٌ في ثمانيةٍ من الأشكال التسعة**
   ⇒ ⛔ **فلا صنفَ يُضاف إلى قالب، ولا شرطَ في PHP، ولا سطرَ يعرف أيُّ شكلٍ
   مفعَّل**. الشكلُ يغيّر رقمًا، والورقةُ تفعل الباقي — وهو مذهبُ الثمانيةِ
   والعشرين متغيّرًا كلِّها في هذا الملفّ.

   **والحشوةُ تتبع العرضَ** فلا يركب الشريطُ على أول الحرف: `calc` تعطي صفرًا
   حين يكون العرضُ صفرًا، فلا تتحرّك الكروتُ في الأشكال الثمانية الأخرى قيدَ
   بكسل. ⚠️ **والجانبُ منطقيٌّ لا يمينيّ** (`inline-start`) — والموقعُ عربيٌّ
   من اليمين، **فالشريطُ على يمين الكرت حيث يبدأ القارئ** ⛔ لا على يساره. */
.card-item {
    border-inline-start: var(--edge-width, 0) solid var(--primary);
    padding-inline-start: calc(var(--edge-width, 0) * 2.5);
}

/* 🔴 **تصحيحٌ مؤرَّخ — 11/08/2026، والعيّنةُ البصريةُ في P-076 §٤ هي التي أمسكته.**

   **والنصُّ فوقه يبقى ولا يُمحى** (RULES §٩/١) — **وما تغيّر أن الشكلَ لم يكن
   يصل كرتَ المشروع**.

   ⛔ **والعيبُ مقيسٌ لا مُستنتَج**: `--edge-width: 4px` كان يخرج صحيحًا في
   الصفحة، **و`.card-item` تحمله فعلًا** — لكنّ صفحةَ المشاريع لا تحمل منها
   واحدةً: كرتُ المشروع `.pcard` عائلةٌ أخرى. ⇒ **فشكلٌ اسمُه «بحدٍّ جانبيّ»
   كان يُقرأ في الأخبار ولا يُقرأ في المشاريع** — **وهي الصفحةُ التي تحمل زرَّ
   التبرّع**، **فالفارقُ بينه وبين «مطبوع» كان صفرًا حيث ينظر المتبرّع**.

   ⚠️ **ولماذا عنصرٌ زائفٌ لا `border-inline-start` كما في `.card-item`**:
   `.pcard` تحمل حدًّا على جوانبها الأربعة، **و`border-inline-start: 0 solid`
   تمحو ذلك الحدَّ في الأشكال الثمانية الأخرى** ⇒ **فتتغيّر ثمانيُ شاشاتٍ لأجل
   واحدة**. **والعنصرُ الزائفُ عرضُه صفرٌ فلا يرسم شيئًا** ⇒ **لا مساسَ
   بالثماني**، **مقيسًا بالبصمة لا بالظنّ**.

   **و`.pcard` أصلًا `position: relative` و`overflow: hidden`** ⇒ ⛔ **فلا سطرَ
   يُضاف لها لأجل هذا. والجانبُ منطقيٌّ لا يمينيّ**، على قاعدة السطر فوقه. */
.pcard::after {
    content: '';
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: var(--edge-width, 0);
    background: var(--primary);
    pointer-events: none;
}

.card-item__cover,
.cover {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

/* A missing cover is never a gap. The year stands where the picture would be,
   at the same size, so a row of them stays a row. */
.card-item__cover--year,
.cover--year {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 3 / 4;
    background: var(--surface);
    color: var(--text-quiet);
    font-size: 1.75rem;
    font-weight: 700;
}

.plain-list {
    margin: 0;
    padding: 0;
    list-style: none;
    max-width: var(--reading-width);
}

.plain-list__entry {
    padding: calc(0.75rem * var(--space)) 0;
    border-bottom: var(--border-width) solid var(--line);
}

/* ---------- reports ---------- */

.timeline {
    margin: 0;
    padding: 0 1.25rem 0 0;
    list-style: none;
    border-right: var(--border-width-strong) solid var(--line);
}

.timeline__entry {
    position: relative;
    padding: 0 1.5rem 2rem 0;
}

.timeline__entry::before {
    content: '';
    position: absolute;
    top: 0.6rem;
    right: -1.85rem;
    width: 0.9rem;
    height: 0.9rem;
    border-radius: 50%;
    background: var(--primary);
}

.timeline__year {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--headings);
}

/* Three in a row, like the cards. Fitting as many as the width allowed put
   five squares in a row, and the plan draws three. */
.year-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: calc(1.25rem * var(--space));
}

.year-square {
    padding: calc(1.25rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    text-align: center;
    background: var(--page);
    box-shadow: var(--shadow);
    transition: transform var(--transition), box-shadow var(--transition);
}

.year-square:hover {
    transform: var(--hover-transform);
    box-shadow: var(--hover-shadow);
}

.year-square__year {
    display: block;
    font-size: 2.25rem;
    font-weight: 700;
    color: var(--headings);
}

/* ---------- publications ---------- */

/* Books standing on shelves.
   Every cover in a row rests on the same line whatever its height — they are
   aligned by their bottom, the way books stand, not hung by their top — and
   every row carries its own shelf. The shelf is drawn under each book rather
   than under the whole grid, and the columns touch, so the pieces join into
   one line per row. */
.shelf {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    row-gap: calc(2rem * var(--space));
    column-gap: 0;
}

.shelf__stand {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    min-height: 17rem;
    padding: 0 0.75rem 0.85rem;
    border-bottom: var(--border-width-strong) solid var(--line-strong);
}

/* An empty place at the end of the last row. It holds no book and carries no
   writing: it is there so the shelf under a short row still runs the whole
   width, the way a shelf does. It starts at the top of its row, or it would
   drop its piece of the line to the bottom of the row instead of onto the
   line the books are standing on. */
.shelf__stand--empty {
    align-self: start;
}

.shelf__stand .cover {
    width: auto;
    max-width: 100%;
    max-height: 16rem;
}

.shelf__stand .cover--year {
    width: auto;
    height: 16rem;
}

.shelf__book > .entry__title,
.shelf__book > .file-buttons {
    padding: 0 0.75rem;
}

.shelf__book > .entry__title {
    margin-top: 0.6rem;
}

/* The publications lead: a large cover on one side with the writing beside it,
   which is what that plan draws. The news lead is a different shape and has a
   block of its own. */
.lead {
    display: grid;
    grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);
    gap: 2rem;
    margin: 0 0 2.5rem;
    align-items: start;
}

/* ---------- the board ---------- */

/* A row holds exactly the members put in it — three, or fewer at the top of a
   pyramid. Laying the row out as wrapping boxes let a row of three break into
   two and one whenever the boxes were a little too wide for the page; counted
   columns cannot break. The columns are as wide as the member needs and no
   wider, and the group is centred. */
.board-row {
    display: grid;
    grid-template-columns: repeat(var(--members, 3), minmax(0, var(--member-width, 16rem)));
    justify-content: center;
    gap: calc(2rem * var(--space));
    margin: 0 0 calc(2rem * var(--space));
}

/* A member with the name beside the picture needs a wider column than one with
   the name under it. The width belongs to the row, because the row is what
   divides it. */
.board-row--beside {
    --member-width: 20rem;
}

.member {
    text-align: center;
}

/* The name beside the picture, and the biography under both across the whole
   card — not squeezed into the column beside the picture. */
.member--beside {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 0 1rem;
    text-align: right;
}

.member--beside .member__facts {
    align-self: center;
}

.member--beside .member__biography {
    grid-column: 1 / -1;
    margin-top: 0.85rem;
}

.member__image {
    display: block;
    width: 8rem;
    height: 8rem;
    margin: 0 auto 0.75rem;
    object-fit: cover;
    background: var(--surface);
}

.member--beside .member__image {
    margin: 0;
}

.member__image--circle {
    border-radius: 50%;
}

.member__image--square {
    border-radius: var(--radius);
}

.member__image--letter {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-quiet);
    font-size: 2.5rem;
    font-weight: 700;
}

.member__name {
    margin: 0 0 0.2rem;
    font-size: 1.1rem;
    color: var(--headings);
}

.member__role {
    margin: 0 0 0.4rem;
    color: var(--text-quiet);
}

.member__biography {
    margin: 0;
}

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

/* Form four: the first item leads the page with its picture across the whole
   width and the title underneath it. It is a headline, so it is not a small
   picture with writing beside it — that is form two. */
.wide-lead {
    margin: 0 0 2.5rem;
}

.wide-lead__cover {
    display: block;
    width: 100%;
    max-height: 24rem;
    object-fit: cover;
    border-radius: var(--radius);
    margin: 0 0 1rem;
}

.wide-lead__title {
    margin: 0 0 0.35rem;
    font-size: 1.6rem;
    line-height: 1.6;
    font-weight: 700;
    color: var(--headings);
}

.wide-lead__title a {
    color: inherit;
}

.filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin: 0 0 2rem;
}

/* 🔴 The two lines that keep a filter row inside a telephone — `min-width` and
   `max-width`, and neither of them alone is enough (ع-١, `DEFERRED` ٥٨).

   **What went wrong, measured rather than guessed.** A `<select>` asks to be as
   wide as its longest option, and that width is *content*, not a wish: a flex
   item carries `min-width: auto`, so the row could not shrink it. One category
   named at length made the box 653px on a 390px screen, the row could not give
   way, and the whole projects page — cards, pager and all — was dragged out
   past the edge of the phone with a sideways scroll under it. Measured by
   isolation: hiding that one category on the same copy took the box to 150px
   and the document back to 390.

   `min-width: 0` lets the row shrink the box at all; `max-width: 100%` stops it
   at the width of the row when it lands on a line of its own. ⛔ **And nothing
   is taken away to buy it**: every category keeps its whole name in the list
   the browser opens, the names in the database are untouched, and the filter
   still filters by all of them. What is clipped is the closed box's own view of
   the chosen name, and `text-overflow` marks the clip so it reads as a name
   continuing rather than a name ending there.

   ✅ **It reaches the news page's two boxes in the same stroke**, and that is
   why the rule is written on `.filters` and not on one page: «كل السنوات» is
   short, but a source is whatever the owner typed, and it would have arrived at
   exactly the same place. */
.filters input,
.filters select {
    padding: 0.45rem 0.7rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--page);
    color: var(--text);
    font: inherit;
    min-width: 0;
    max-width: 100%;
}

.filters select {
    text-overflow: ellipsis;
}

.year-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 2rem;
}

.year-bar__year {
    padding: 0.35rem 0.8rem;
    border: var(--border-width) solid var(--line);
    border-radius: 999px;
    color: var(--text);
    text-decoration: none;
}

.year-bar__year--current {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--on-primary);
}

.pagination {
    margin: 2rem 0 0;
}

.pages {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.pages__link {
    padding: 0.35rem 0.75rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    color: var(--text);
    text-decoration: none;
}

.pages__link--current {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--on-primary);
}

.pages__link--off {
    color: var(--text-quiet);
}

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

.form-page__body {
    display: grid;
    gap: 2rem;
}

/* Form two: the plan puts the picture on the left and the form on its right,
   so the columns are placed by hand rather than taken in the order they are
   written — the picture stays first in the writing so a phone, which has one
   column, still leads with it. */
.form-page--2 .form-page__body {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
}

.form-page--2 .form-page__aside {
    grid-column: 2;
    grid-row: 1;
}

.form-page--2 .form-page__main {
    grid-column: 1;
    grid-row: 1;
}

.form-page--3 .form-page__main,
.form-page--5 .form-page__main {
    max-width: var(--reading-width);
    margin: 0 auto;
}

.form-page__text {
    white-space: pre-line;
}

.form-page__text--large {
    font-size: 1.3rem;
    text-align: center;
}

/* Form four lays the picture behind the whole page. The veil over it is the
   page's own colour, computed centrally, so the writing stays readable on any
   picture in any palette. */
.form-page--4 {
    padding: 2rem;
    border-radius: var(--radius);
    background-size: cover;
    background-position: center;
}

.form-page--4 .form-page__main {
    max-width: var(--reading-width);
    margin: 0 auto;
    padding: 1.5rem;
    border-radius: var(--radius);
    background: var(--page-veil);
}

.public-form {
    max-width: var(--reading-width);
}

.public-field {
    margin: 0 0 1rem;
}

.public-field label {
    display: block;
    margin: 0 0 0.3rem;
    font-weight: 700;
}

.public-field__required {
    color: var(--error);
    font-weight: 400;
    font-size: 0.85rem;
}

.public-field__hint {
    display: block;
    margin-top: 0.25rem;
    color: var(--text-quiet);
    font-size: 0.9rem;
}

.public-field input,
.public-field select,
.public-field textarea,
.phone input,
.phone select {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--page);
    color: var(--text);
    font: inherit;
}

.phone {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    gap: 0.5rem;
}

/* Seen by nobody, and filled in by a machine that reads the page rather than
   looks at it.
   It is hidden by being clipped to nothing, not by being pushed thousands of
   pixels to the side: pushing it sideways stretched the page to ten thousand
   pixels wide and gave every form page a horizontal scroll into emptiness. */
.nobody {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.notice-public {
    padding: 0.8rem 1rem;
    border: var(--border-width) solid var(--ok-border);
    border-radius: var(--radius);
    background: var(--ok-bg);
}

/* ---------- and the three tones a notice may carry (P-072 ن-٢) ----------
 *
 * 🔴 **One shape, three meanings.** Until 11/08/2026 every notice on this site
 * wore the same green — and the four sentences a basket says when a project
 * leaves it had just been made to differ in every word. **The text told four
 * things apart and the colour still said one**, which the owner's own eye found
 * in `R-083`: «الأخضرُ يصدق على «اكتمل جمع التبرعات» ويكذب على «لم يعد هذا
 * المشروع متاحًا»».
 *
 * ⛔ **Not one of the three is the theme's colour.** They are written pairs in
 * `App\Support\SiteTheme` beside `--error`, ⛔ never computed from the palette:
 * a state's meaning does not change when the association changes its green.
 *
 * ⚠️ **The base rule above is untouched**, so every other notice on this site —
 * the message sent, the payment result, the receipt — reads exactly as it read
 * yesterday. Only what asks for a tone gets one. */
.notice-public--good {
    border-color: var(--ok-border);
    background: var(--ok-bg);
}

.notice-public--note {
    border-color: var(--note-border);
    background: var(--note-bg);
}

.notice-public--warn {
    border-color: var(--warn-border);
    background: var(--warn-bg);
}

.error-public {
    display: block;
    margin-top: 0.3rem;
    color: var(--error);
}

/* ---------- less motion, when the visitor asked for less ---------- */

/* Every movement the theme makes stops here: the symbol does not drop, the
   cards do not lift, and nothing eases. The visitor asked the device for
   less motion, and the device is obeyed without being asked twice. */
@media (prefers-reduced-motion: reduce) {
    .occasion {
        animation: none;
    }

    .card-item,
    .year-square,
    .menu-list--card .menu-list__link,
    .home-partner__logo {
        transition: none;
    }

    .card-item:hover,
    .year-square:hover,
    .menu-list--card .menu-list__link:hover {
        transform: none;
    }
}

/* ---------- print ---------- */

/* Print ignores the theme, always: a white page, black writing, no decoration
   and nothing hanging — whatever the screen shows. A page printed from a dark
   theme must not come out of the printer as a black sheet. These are the only
   raw colours in this file, and they are the rule itself, not a leak. */
@media print {
    :root {
        --primary: #000000;
        --on-primary: #ffffff;
        --page: #ffffff;
        --surface: #ffffff;
        --text: #000000;
        --text-quiet: #444444;
        --headings: #000000;
        --line: #bbbbbb;
        --line-strong: #888888;
        --strip: #ffffff;
        --on-strip: #000000;
        --on-strip-quiet: #444444;
        --strip-line: #bbbbbb;
        --strip-accent: #000000;
        --error: #000000;
        --ok-border: #888888;
        --ok-bg: #ffffff;
        /* The three tones flatten with everything else: a printed page says
           what it says in words, and a printer is not asked for three shades
           of paper. */
        --note-border: #888888;
        --note-bg: #ffffff;
        --warn-border: #888888;
        --warn-bg: #ffffff;
        --page-veil: #ffffff;
        --shadow: none;
        --shadow-pop: none;
        --hover-shadow: none;
        --hover-transform: none;
        --decoration-image: none;
    }

    .occasion-well,
    .whatsapp-float,
    .site-header__menu {
        display: none;
    }

}

/* ---------- the phone ---------- */

@media (max-width: 48rem) {
    /* The wide list goes out of the page, and the one that opens from the side
       takes its place.

       Written with the header in front of it so it carries the same weight as
       the rules that lay each shape out. Those rules name two classes and set
       a display of their own; a rule naming one class loses to them however
       far down the file it sits, because a media query adds no weight. Shapes
       one, three and four were showing both menus at once on a phone until
       this line was made to match them. */
    .site-header .site-header__links {
        display: none;
    }

    .site-header__menu {
        display: block;
        margin-inline-start: auto;
    }

    /* The button is the browser's own summary, and the panel is the rest of
       the element — no script, no overlay to dismiss, and it closes by
       pressing the button again. */
    .site-header__menu > summary {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 2.75rem;
        height: 2.75rem;
        margin-inline-start: auto;
        border: var(--border-width) solid var(--line);
        border-radius: var(--radius);
        list-style: none;
        cursor: pointer;
    }

    .site-header__menu > summary::-webkit-details-marker {
        display: none;
    }

    /* Three lines, drawn rather than written, so the button needs no font and
       no picture. */
    .site-header__bars,
    .site-header__bars::before,
    .site-header__bars::after {
        display: block;
        width: 1.15rem;
        height: 2px;
        background: var(--text);
    }

    .site-header__bars {
        position: relative;
    }

    .site-header__bars::before,
    .site-header__bars::after {
        content: '';
        position: absolute;
        inset-inline-start: 0;
    }

    .site-header__bars::before {
        top: -0.35rem;
    }

    .site-header__bars::after {
        top: 0.35rem;
    }

    .site-header__nav {
        position: fixed;
        top: 0;
        bottom: 0;
        inset-inline-start: 0;
        width: min(20rem, 84vw);
        padding: 1.5rem 1.25rem;
        background: var(--page);
        border-inline-end: var(--border-width) solid var(--line);
        box-shadow: var(--shadow-pop);
        overflow-y: auto;
        z-index: 40;
    }

    .site-header__nav .menu-list {
        flex-direction: column;
        align-items: stretch;
        gap: 0.2rem;
    }

    /* Inside the panel a drop-down opens in place, under its own name. There
       is no room beside it for a floating list. */
    .menu-list__children {
        position: static;
        margin: 0.2rem 0 0.4rem;
        border: 0;
        box-shadow: none;
        padding-inline-start: 1rem;
    }

    /* The strip and the accounts go inside the menu, so the phone line holds
       the logo and the basket and nothing else. */
    .site-header__strip {
        display: none;
    }

    .site-header__side .socials {
        display: none;
    }

    .site-header__inside-menu {
        display: block;
        margin-top: 1.5rem;
        padding-top: 1.25rem;
        border-top: var(--border-width) solid var(--line);
    }

    .site-header__inside-menu .socials {
        margin-top: 0.75rem;
    }

    .site-header__logo {
        height: 32px;
    }

    .site-header__main .site-header__inner,
    .site-header--2 .site-header__main .site-header__inner,
    .site-header--4 .site-header__main .site-header__inner {
        display: flex;
        min-height: 64px;
        gap: 0.75rem;
        padding-block: 0.6rem;
    }

    .site-header--2 .site-header__side,
    .site-header--4 .site-header__side {
        margin-inline-start: 0;
    }

    /* Nothing hangs on a narrow phone: the width it would take is the reader's. */
    .occasion-well {
        display: none;
    }

    /* The columns of the footer come one under another. No folding and no
       accordion: a footer that has to be opened is a footer nobody opens.

       Named with the footer in front of it for the same reason the header list
       is: the rules that lay each shape out name two classes, and a rule naming
       one loses to them however far down the file it sits. Without this the
       columns stayed side by side on a phone, four of them squeezed into a
       telephone's width. */
    .site-footer .site-footer__inner {
        grid-auto-flow: row;
        grid-template-columns: minmax(0, 1fr);
        gap: 2rem;
        padding-block: 2rem;
    }

    /* Except the single bar, which becomes two columns rather than one. */
    .site-footer--4 .site-footer__inner {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* On a phone the three tracks become one, and the closing line keeps its
       place in the middle with the accounts under it. */
    .site-footer__bottom-inner {
        grid-template-columns: minmax(0, 1fr);
        justify-items: center;
        gap: 0.75rem;
    }

    .site-footer__bottom-side:empty {
        display: none;
    }

    .site-footer__bottom-side--end {
        justify-content: center;
    }

    /* Two columns of links is one column on a phone. */
    .site-footer__column .menu-list--split {
        column-count: 1;
    }
}

/* One column on a phone, always. Nothing here scrolls sideways. */
@media (max-width: 48rem) {
    .beside,
    .lead,
    .cards,
    .year-grid,
    .board-row,
    .form-page--2 .form-page__body {
        grid-template-columns: minmax(0, 1fr);
    }

    /* A column placed by hand must be released here, or asking for column two
       of a one-column grid makes a second column and the page scrolls
       sideways. */
    .beside__image,
    .beside__text,
    .form-page--2 .form-page__aside,
    .form-page--2 .form-page__main {
        grid-column: auto;
        grid-row: auto;
    }

    .row-item {
        grid-template-columns: minmax(0, 1fr);
    }

    .member--beside {
        grid-template-columns: auto minmax(0, 1fr);
    }

    /* Two books to a row on a phone, and no empty places: an empty place is
       there to finish a line, and a line that would sit under nothing is worse
       than a short one. */
    .shelf {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .shelf__stand {
        min-height: 13rem;
    }

    .shelf__stand .cover {
        max-height: 12rem;
    }

    .shelf__stand .cover--year {
        height: 12rem;
    }

    .shelf__stand--empty {
        display: none;
    }

    .phone {
        grid-template-columns: minmax(0, 1fr);
    }

    .page {
        padding: 1.75rem 1rem 3rem;
    }

    .page__title {
        font-size: 1.6rem;
    }
}

/* ---------- the home page ---------- */

/* The logo leads home now, and a link must not look like one: the brand keeps
   exactly the face it had when it was a plain box. */
.site-header__brand {
    color: inherit;
    text-decoration: none;
}

.home-block__head {
    max-width: 44rem;
    margin: 0 auto 1.75rem;
    text-align: center;
}

.home-block__title {
    margin: 0 0 0.5rem;
    color: var(--headings);
    font-size: 1.7rem;
}

.home-block__sentence {
    margin: 0;
    color: var(--text-quiet);
}

.home-block__more {
    margin: 1.75rem 0 0;
    text-align: center;
}

/* ---------- the divider between blocks ---------- */

.divider {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.9rem;
}

.divider--small {
    margin: 1.25rem auto;
}

.divider--medium {
    margin: 2.5rem auto;
}

.divider--large {
    margin: 4rem auto;
}

/* An empty space is exactly that: its size is its whole meaning. */
.divider--form-1 {
    height: 0;
}

.divider--form-2 .divider__line {
    width: 100%;
    border-top: var(--border-width) solid var(--line);
}

.divider--form-3 .divider__line {
    width: 7rem;
    border-top: var(--border-width-strong) solid var(--line-strong);
}

/* A line fading out at both ends — drawn with the theme's own line colour,
   fading to nothing. */
.divider--form-4 .divider__line {
    width: 100%;
    height: var(--border-width);
    background: linear-gradient(to left, transparent, var(--line-strong), transparent);
}

.divider--form-5 .divider__side,
.divider--form-6 .divider__side {
    width: 6rem;
    border-top: var(--border-width) solid var(--line);
}

.divider--form-5 .divider__diamond {
    width: 0.6rem;
    height: 0.6rem;
    border: var(--border-width) solid var(--line-strong);
    transform: rotate(45deg);
}

/* The association logo, very small and light grey like the partners' logos:
   it is a coloured picture, not a drawn shape, so it never takes the theme
   colour — and left as it is, it could vanish on a dark theme or look
   crowded at this size. */
.divider--form-6 .divider__logo {
    max-height: 1.75rem;
    max-width: 5rem;
    object-fit: contain;
    filter: grayscale(1);
    opacity: 0.45;
}

/* ---------- the slider ---------- */

/* It turns by the stylesheet alone. The track carries every slide side by
   side; a keyframe walk shows each one for the owner's seconds. The dots are
   labels for hidden radios: the first press stops the walk for good and
   stands on that slide — and with reduced motion the walk never starts. */
.home-slider {
    position: relative;
}

.home-slider__window {
    overflow: hidden;
    border-radius: var(--radius);
}

.home-slider__track {
    display: flex;
    align-items: stretch;
    width: calc(var(--slides) * 100%);
}

.home-slider--count-2 .home-slider__track {
    animation: home-turn-2 calc(var(--slides) * var(--slide-seconds)) linear infinite;
}

.home-slider--count-3 .home-slider__track {
    animation: home-turn-3 calc(var(--slides) * var(--slide-seconds)) linear infinite;
}

.home-slider--count-4 .home-slider__track {
    animation: home-turn-4 calc(var(--slides) * var(--slide-seconds)) linear infinite;
}

.home-slider--count-5 .home-slider__track {
    animation: home-turn-5 calc(var(--slides) * var(--slide-seconds)) linear infinite;
}

.home-slider--count-6 .home-slider__track {
    animation: home-turn-6 calc(var(--slides) * var(--slide-seconds)) linear infinite;
}

/* The first press on a dot ends the walk and stands on that slide. */
.home-slider:has(.home-slider__radio:checked) .home-slider__track {
    animation: none;
}

.home-slider:has(.home-slider__radio:nth-of-type(1):checked) .home-slider__track {
    transform: translateX(0);
}

.home-slider:has(.home-slider__radio:nth-of-type(2):checked) .home-slider__track {
    transform: translateX(calc(100% / var(--slides)));
}

.home-slider:has(.home-slider__radio:nth-of-type(3):checked) .home-slider__track {
    transform: translateX(calc(2 * 100% / var(--slides)));
}

.home-slider:has(.home-slider__radio:nth-of-type(4):checked) .home-slider__track {
    transform: translateX(calc(3 * 100% / var(--slides)));
}

.home-slider:has(.home-slider__radio:nth-of-type(5):checked) .home-slider__track {
    transform: translateX(calc(4 * 100% / var(--slides)));
}

.home-slider:has(.home-slider__radio:nth-of-type(6):checked) .home-slider__track {
    transform: translateX(calc(5 * 100% / var(--slides)));
}

.home-slide {
    position: relative;
    display: grid;
    width: calc(100% / var(--slides));
    min-height: clamp(22rem, 42vw, 32rem);
    flex-shrink: 0;
    overflow: hidden;
}

/* Form one: the picture across the whole width and the writing over it. */
.home-slide--form-1 .home-slide__media {
    position: absolute;
    inset: 0;
}

.home-slide--form-1 .home-slide__image {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.home-slide__veil {
    position: absolute;
    inset: 0;
    background: var(--strip);
    opacity: 0.45;
}

.home-slide--form-1 .home-slide__content {
    position: relative;
    z-index: 1;
    align-self: center;
    justify-self: start;
    max-width: 34rem;
    padding: 2.5rem;
    color: var(--on-strip);
}

.home-slide--form-1 .home-slide__title,
.home-slide--form-1 .home-slide__kicker {
    color: var(--on-strip);
}

.home-slide--form-1 .home-slide__body {
    color: var(--on-strip-quiet);
}

/* Form two: halves — the picture on one side and the writing on the other. */
.home-slide--form-2 {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    background: var(--surface);
}

.home-slide--form-2 .home-slide__media--half {
    order: 2;
    min-height: 0;
}

.home-slide--form-2 .home-slide__image {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.home-slide--form-2 .home-slide__content {
    order: 1;
    align-self: center;
    padding: 2.5rem;
}

/* Form three: writing alone, on the theme's colour with its decoration. */
.home-slide--form-3 {
    background-color: var(--strip);
    background-image: var(--decoration-image);
}

.home-slide--form-3 .home-slide__content {
    align-self: center;
    justify-self: center;
    max-width: 38rem;
    padding: 2.5rem;
    text-align: center;
    color: var(--on-strip);
}

.home-slide--form-3 .home-slide__title,
.home-slide--form-3 .home-slide__kicker {
    color: var(--on-strip);
}

.home-slide--form-3 .home-slide__body {
    color: var(--on-strip-quiet);
}

/* Form four: two or three square pictures in small columns, the writing
   beside them. */
.home-slide--form-4 {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
    align-items: center;
    background: var(--surface);
}

.home-slide--form-4 .home-slide__content {
    padding: 2.5rem;
}

.home-slide--form-4 .home-slide__columns {
    display: flex;
    gap: 0.9rem;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
}

.home-slide--form-4 .home-slide__square {
    flex: 1 1 0;
    min-width: 0;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border-radius: var(--radius-small);
}

.home-slide--form-4 .home-slide__square .home-slide__image {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.home-slide__kicker {
    margin: 0 0 0.4rem;
    font-size: 0.95rem;
    letter-spacing: 0.02em;
    color: var(--text-quiet);
}

.home-slide__title {
    margin: 0 0 0.6rem;
    font-size: clamp(1.5rem, 3vw, 2.3rem);
    color: var(--headings);
}

.home-slide__body {
    margin: 0 0 1.1rem;
    color: var(--text-quiet);
}

.home-slide__button {
    display: inline-block;
}

/* The dots under the slide, showing how many slides there are. */
.home-slider__dots {
    display: flex;
    justify-content: center;
    gap: 0.6rem;
    padding: 0.9rem 0 0;
}

.home-slider__dot {
    width: 0.8rem;
    height: 0.8rem;
    border: var(--border-width-strong) solid var(--line-strong);
    border-radius: 50%;
    cursor: pointer;
}

.home-slider__dot:hover {
    border-color: var(--primary);
}

.home-slider:has(.home-slider__radio:nth-of-type(1):checked) .home-slider__dot:nth-of-type(1),
.home-slider:has(.home-slider__radio:nth-of-type(2):checked) .home-slider__dot:nth-of-type(2),
.home-slider:has(.home-slider__radio:nth-of-type(3):checked) .home-slider__dot:nth-of-type(3),
.home-slider:has(.home-slider__radio:nth-of-type(4):checked) .home-slider__dot:nth-of-type(4),
.home-slider:has(.home-slider__radio:nth-of-type(5):checked) .home-slider__dot:nth-of-type(5),
.home-slider:has(.home-slider__radio:nth-of-type(6):checked) .home-slider__dot:nth-of-type(6) {
    background: var(--primary);
    border-color: var(--primary);
}

/* The walk itself, one set of steps per count: each slide holds its segment,
   slides over, and the last sweeps back to the first. In this right-to-left
   page the track moves rightward, so the steps are positive. */
@keyframes home-turn-2 {
    0%, 45% { transform: translateX(0); }
    50%, 95% { transform: translateX(50%); }
    100% { transform: translateX(0); }
}

@keyframes home-turn-3 {
    0%, 28% { transform: translateX(0); }
    33.33%, 61.33% { transform: translateX(33.3333%); }
    66.67%, 95% { transform: translateX(66.6667%); }
    100% { transform: translateX(0); }
}

@keyframes home-turn-4 {
    0%, 21% { transform: translateX(0); }
    25%, 46% { transform: translateX(25%); }
    50%, 71% { transform: translateX(50%); }
    75%, 95% { transform: translateX(75%); }
    100% { transform: translateX(0); }
}

@keyframes home-turn-5 {
    0%, 17% { transform: translateX(0); }
    20%, 37% { transform: translateX(20%); }
    40%, 57% { transform: translateX(40%); }
    60%, 77% { transform: translateX(60%); }
    80%, 95% { transform: translateX(80%); }
    100% { transform: translateX(0); }
}

@keyframes home-turn-6 {
    0%, 14% { transform: translateX(0); }
    16.67%, 31% { transform: translateX(16.6667%); }
    33.33%, 47.6% { transform: translateX(33.3333%); }
    50%, 64.3% { transform: translateX(50%); }
    66.67%, 81% { transform: translateX(66.6667%); }
    83.33%, 95% { transform: translateX(83.3333%); }
    100% { transform: translateX(0); }
}

/* ---------- the statistics ---------- */

.home-stats {
    position: relative;
    border-radius: var(--radius);
}

.home-stats__inner {
    position: relative;
    z-index: 1;
}

.home-stats__items {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 1.5rem;
    justify-items: center;
    text-align: center;
}

.home-stat {
    display: grid;
    justify-items: center;
    gap: 0.35rem;
}

.home-stat__icon svg {
    width: 3rem;
    height: 3rem;
    color: var(--primary);
}

.home-stat__value {
    font-size: 2rem;
    font-weight: 700;
    color: var(--headings);
}

.home-stat__label {
    color: var(--text-quiet);
}

/* Form one: one row with upright separators between the numbers. */
.home-stats--form-1 .home-stat + .home-stat {
    border-inline-start: var(--border-width) solid var(--line);
    padding-inline-start: 1.5rem;
}

.home-stats--form-1 .home-stats__items {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1.5rem 0;
}

.home-stats--form-1 .home-stat {
    padding-inline: 1.5rem;
}

/* Form two: cards. */
.home-stats--form-2 .home-stat {
    width: 100%;
    padding: 1.5rem 1rem;
    background: var(--surface);
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

/* Form three: the first number large and the rest small. */
.home-stats--form-3 .home-stats__items {
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
}

.home-stats--form-3 .home-stat:first-child {
    grid-row: span 2;
    align-self: center;
}

.home-stats--form-3 .home-stat:first-child .home-stat__value {
    font-size: 3.4rem;
}

.home-stats--form-3 .home-stat:first-child .home-stat__icon svg {
    width: 4rem;
    height: 4rem;
}

/* Form four: on the theme's colour. */
.home-stats--form-4 {
    background: var(--strip);
    padding: 2.5rem 1.5rem;
}

.home-stats--form-4 .home-stat__value,
.home-stats--form-6 .home-stat__value {
    color: var(--on-strip);
}

.home-stats--form-4 .home-stat__label,
.home-stats--form-6 .home-stat__label {
    color: var(--on-strip-quiet);
}

.home-stats--form-4 .home-stat__icon svg,
.home-stats--form-6 .home-stat__icon svg {
    color: var(--strip-accent);
}

.home-stats--form-4 .home-block__title,
.home-stats--form-6 .home-block__title {
    color: var(--on-strip);
}

.home-stats--form-4 .home-block__sentence,
.home-stats--form-6 .home-block__sentence {
    color: var(--on-strip-quiet);
}

/* Form five: huge numbers with room to breathe. */
.home-stats--form-5 {
    padding: 3.5rem 1.5rem;
}

.home-stats--form-5 .home-stats__items {
    gap: 3rem;
}

.home-stats--form-5 .home-stat__value {
    font-size: 3.2rem;
}

/* Form six: over a dimmed picture. The dimming is the theme's strip colour at
   a fixed depth — set by the system, not a choice. */
.home-stats--form-6 {
    overflow: hidden;
    padding: 3rem 1.5rem;
}

.home-stats__backdrop {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.home-stats__veil {
    position: absolute;
    inset: 0;
    background: var(--strip);
    opacity: 0.72;
}

/* Form seven: the writing on one side and the numbers on the other. */
.home-stats--form-7 .home-stats__inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
    gap: 2rem;
    align-items: center;
}

.home-stats--form-7 .home-block__head {
    margin: 0;
    text-align: start;
}

/* ---------- the news and publications blocks ---------- */

/* Fewer pieces than the chosen count: what exists is shown at its own size
   and centred — never stretched to fill the width. */
.home-news__cards,
.home-covers {
    justify-content: center;
}

.home-covers .card-item .cover {
    align-self: center;
}

/* Cards with the covers held to one height, the shelf keeping natural ones. */
.home-covers--even .cover {
    height: 16rem;
    width: auto;
    object-fit: contain;
}

.home-shelf {
    justify-content: center;
}

/* ---------- the board block ---------- */

.home-board__row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 2rem;
    text-align: center;
}

.home-board__row .member,
.home-board__cards .member {
    display: grid;
    justify-items: center;
    gap: 0.3rem;
}

.home-board__cards {
    justify-content: center;
}

.home-board__split {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 2.5rem;
    align-items: center;
    justify-content: center;
}

.home-board__chief {
    display: grid;
    justify-items: center;
    gap: 0.3rem;
    text-align: center;
}

.home-board__chief .member__image {
    width: 11rem;
    height: 11rem;
    font-size: 3.5rem;
}

.home-board__others {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    justify-content: center;
    text-align: center;
}

.home-board__others .member {
    display: grid;
    justify-items: center;
    gap: 0.2rem;
}

.home-board__others .member__image {
    width: 5.5rem;
    height: 5.5rem;
    font-size: 1.6rem;
}

/* The chairman's word: one voice with its owner's photo — not a list. */
.home-board__word {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 2rem;
    align-items: center;
    max-width: 46rem;
    margin: 0 auto;
}

.home-board__quote {
    margin: 0;
    padding-inline-start: 1.25rem;
    border-inline-start: var(--border-width-strong) solid var(--primary);
}

.home-board__quote p {
    margin: 0 0 0.6rem;
    font-size: 1.15rem;
    color: var(--text);
}

/* ---------- the invitation blocks ---------- */

.home-call__strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 1.25rem;
    padding: 1.5rem 2rem;
    background: var(--strip);
    border-radius: var(--radius);
}

.home-call__line {
    margin: 0;
    font-size: 1.2rem;
    color: var(--on-strip);
}

.home-call__beside {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 2rem;
    align-items: center;
}

.home-call__image {
    width: 100%;
    border-radius: var(--radius);
    object-fit: cover;
}

.home-call__text {
    font-size: 1.1rem;
    color: var(--text);
}

.home-call__text p {
    margin-top: 0;
}

/* Centred with the decoration behind and the symbol above, in theme colour. */
.home-call__centre {
    display: grid;
    justify-items: center;
    gap: 1rem;
    padding: 3rem 1.5rem;
    text-align: center;
    background-color: var(--surface);
    background-image: var(--decoration-image);
    border-radius: var(--radius);
}

.home-call__icon svg {
    width: 3.5rem;
    height: 3.5rem;
    color: var(--primary);
}

.home-call__centre-text {
    margin: 0;
    max-width: 34rem;
    font-size: 1.2rem;
    color: var(--text);
}

/* Over a dimmed picture. */
.home-call__cover {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius);
}

.home-call__backdrop {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.home-call__veil {
    position: absolute;
    inset: 0;
    background: var(--strip);
    opacity: 0.72;
}

.home-call__over {
    position: relative;
    z-index: 1;
    display: grid;
    justify-items: center;
    gap: 1rem;
    padding: 3.5rem 1.5rem;
    text-align: center;
}

.home-call__over .home-call__centre-text {
    color: var(--on-strip);
}

/* The picture in one half and the call with the whole form in the other. */
.home-call__half {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 2rem;
    align-items: stretch;
}

.home-call__half .home-call__image {
    height: 100%;
}

.home-call__form-side .public-form {
    margin-top: 1rem;
}

/* ---------- the partners ---------- */

/* Unified grey, taking their colour back under the pointer. On a touch screen
   there is no pointer to pass, and they simply stay grey. */
.home-partners__grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1.25rem;
}

.home-partner {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 8.5rem;
    aspect-ratio: 1 / 1;
    padding: 1rem;
}

.home-partner__logo {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    filter: grayscale(1);
    opacity: 0.7;
    transition: var(--transition);
}

.home-partner:hover .home-partner__logo {
    filter: none;
    opacity: 1;
}

/* Form two: a grid of bordered squares. */
.home-partners--form-2 .home-partner {
    background: var(--surface);
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius-small);
}

/* Form three: on the theme's colour. */
.home-partners--form-3 {
    background: var(--strip);
    border-radius: var(--radius);
}

.home-partners--form-3 .home-partners__inner {
    padding: 2.5rem 1.5rem;
}

.home-partners--form-3 .home-block__title {
    color: var(--on-strip);
}

.home-partners--form-3 .home-block__sentence {
    color: var(--on-strip-quiet);
}

/* Form four: the sentence in the middle and rows of four. The row is held to
   four by the container's width; the flex wrap centres a short last row on
   its own — «والصف الناقص يتوسّط». */
.home-partners--form-4 .home-partners__grid {
    max-width: calc(4 * 8.5rem + 3 * 1.25rem);
    margin: 0 auto;
}

/* ---------- the home page on a phone ---------- */

@media (max-width: 48rem) {
    /* The writing leaves the picture: the picture above and the writing under
       it, and the whole face capped near seventy percent of the screen so the
       visitor sees there is more below. */
    .home-slide {
        min-height: 0;
        max-height: 70vh;
        grid-template-columns: minmax(0, 1fr);
        overflow-y: hidden;
    }

    .home-slide--form-1 .home-slide__media {
        position: static;
        order: 1;
        max-height: 34vh;
    }

    .home-slide--form-1 .home-slide__image,
    .home-slide--form-2 .home-slide__image {
        max-height: 34vh;
    }

    .home-slide--form-1 .home-slide__veil {
        display: none;
    }

    .home-slide--form-1 .home-slide__content {
        position: static;
        order: 2;
        max-width: none;
        color: var(--text);
    }

    .home-slide--form-1 .home-slide__title,
    .home-slide--form-1 .home-slide__kicker {
        color: var(--headings);
    }

    .home-slide--form-1 .home-slide__body {
        color: var(--text-quiet);
    }

    .home-slide--form-2 .home-slide__media--half {
        order: 1;
    }

    .home-slide--form-2 .home-slide__content {
        order: 2;
    }

    .home-slide--form-1 .home-slide__content,
    .home-slide--form-2 .home-slide__content,
    .home-slide--form-3 .home-slide__content,
    .home-slide--form-4 .home-slide__content {
        padding: 1.25rem 1rem 1.5rem;
    }

    /* The squares stay side by side — they are squares, and stacked they
       would make the slide three screens tall. */
    .home-slide--form-4 .home-slide__columns {
        order: 1;
        padding: 1rem 1rem 0;
    }

    .home-slide--form-4 .home-slide__content {
        order: 2;
    }

    /* The button across the screen, and the dots under it in the middle. */
    .home-slide__button {
        display: block;
        width: 100%;
        text-align: center;
    }

    .home-stats--form-7 .home-stats__inner {
        grid-template-columns: minmax(0, 1fr);
    }

    .home-stats--form-7 .home-block__head {
        text-align: center;
    }

    .home-stats__items {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .home-board__split {
        grid-template-columns: minmax(0, 1fr);
        justify-items: center;
    }

    .home-board__word {
        grid-template-columns: minmax(0, 1fr);
        justify-items: center;
        text-align: center;
    }

    .home-board__quote {
        border-inline-start: none;
        border-top: var(--border-width-strong) solid var(--primary);
        padding-inline-start: 0;
        padding-top: 1rem;
    }

    .home-call__beside {
        grid-template-columns: minmax(0, 1fr);
    }

    /* The call and the form above, the picture under them. */
    .home-call__half {
        grid-template-columns: minmax(0, 1fr);
    }

    .home-call__half .home-call__image {
        order: 2;
        height: auto;
    }

    .home-call__form-side {
        order: 1;
    }

    .home-partners--form-4 .home-partners__grid {
        max-width: calc(2 * 8.5rem + 1.25rem);
    }
}

/* ---------- the home page: less motion, and print ---------- */

/* These two blocks stand at the very end of the file on purpose. The slider's
   turn is written as `.home-slider--count-N .home-slider__track` — two class
   names — so stopping it needs the same weight AND a later position: an
   equal-weight rule written earlier loses the tie, and that is exactly what
   was caught — the slider kept turning under reduced motion until this
   block moved here. */
@media (prefers-reduced-motion: reduce) {
    /* The slider stands still on its first slide. The dots keep working — a
       press jumps, and a jump is not motion. */
    .home-slider .home-slider__track {
        animation: none;
    }
}

/* Print shows the first slide alone: the track stands still at the start,
   the window is one slide wide, and the sisters and the dots are not
   printed. The dimming veils go too — a dimmed picture on paper is a grey
   smear. No colours here: print's colours live in the one print block above. */
@media print {
    .home-slider .home-slider__track {
        animation: none;
        transform: none;
        width: 100%;
    }

    .home-slider .home-slide {
        width: 100%;
    }

    .home-slider .home-slide:not(:first-of-type),
    .home-slider .home-slider__dots,
    .home-slide .home-slide__veil,
    .home-stats .home-stats__veil,
    .home-call .home-call__veil {
        display: none;
    }
}

/* ---------- the projects: the card ---------- */

/* One card for the whole site in one of three designs. The projects page, the
   category page and the home block all draw the same element — there is no
   card per list and no design per list, so a design changed once changes
   everywhere and cannot fall out of step with itself.

   Three in a row, counted and not fitted, exactly as the news cards above are
   and for the same reason: letting the browser fit as many as the width allows
   puts four in a row, and four columns are too narrow for the titles this site
   carries. */
.pcards {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: calc(1.5rem * var(--space));
}

/* The picture-beside design gets two to a row and not three. A card that puts
   its picture on the side spends part of its width on the picture, and a third
   of a page minus a picture leaves the title wrapping one word to a line —
   which is what the first browser check showed. The design decides how many
   fit in a row, because that is a fact about the design and not a taste. */
.pcards--design-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* The card stopped being one link in P-018: it carries a form now, and a form
   cannot live inside an <a>. What replaces «the whole card is pressable» is the
   two largest things on it — the picture and the title — each leading to the
   project. The rest is the giving, and it is pressable in its own right. */
/* ① · **الكرتُ يقرأ أرضيّتَه وحبرَه وخطَّه من محورِ الشكل لا من الصفحة** —
   `DEFERRED` ٢٣، 12/08/2026.

   ⛔ **ولا صنفَ أُضيف ولا شرطَ في PHP**: **الافتراضُ في `SiteTheme` هو ما كان
   مكتوبًا هنا حرفًا** — `--card-ground` = `--surface` · `--card-ink` =
   `--text` · `--card-line` = `--line` ⇒ **فالعشرةُ الأخرى تخرج بالبكسل
   نفسِه**، **مُثبَتًا بالبصمة لا بالدعوى** *([`T-093 §٣`])*.

   ⚠️ **و`color: inherit` صارت `var(--card-ink)`** — **والقيمتان واحدةٌ في
   العشرة**: `body` **تحمل `color: var(--text)`**، **و`--card-ink` هي `--text`
   نفسُها فيهنّ. والفرقُ أنّ الوراثةَ لا تُقاد بمحور، والمتغيّرَ يُقاد.** */
.pcard {
    position: relative;
    display: grid;
    overflow: hidden;
    border: var(--border-width) solid var(--card-line);
    border-radius: var(--radius);
    background: var(--card-ground);
    box-shadow: var(--shadow);
    color: var(--card-ink);
    transition: var(--transition);
}

.pcard:hover {
    box-shadow: var(--hover-shadow);
    transform: var(--hover-transform);
}

.pcard__media {
    position: relative;
    display: block;
    min-width: 0;
}

.pcard__media-link {
    display: block;
    height: 100%;
}

/* Square, because the picture the owner is required to choose is square: the
   same file goes into three different frames and only a square source comes
   through all three uncropped.

   ① · **وحافّتُها محورُ تركيبةِ «دائري»** — `DEFERRED` ٢٣، 12/08/2026:
   **الصورةُ مربّعةٌ ومقصوصةٌ بالغطاء أصلًا** ⇒ **فحافّةٌ بنصفِ ضلعها تجعلها
   قرصًا** ⛔ **بلا مقاسٍ يُخترع ولا عنصرٍ يُضاف**. **والقيمةُ صفرٌ في العشرة
   الأخرى فلا ترسم شيئًا**، **على مذهب `--edge-width`.** */
.pcard__image {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: var(--media-radius);
}

.pcard__body {
    position: relative;
    z-index: 1;
    display: grid;
    gap: 0.45rem;
    justify-items: start;
    align-content: start;
    padding: calc(1rem * var(--space));
    min-width: 0;
}

/* The short writing — category, title, sentence, bar — as a piece that can be
   moved. **It is nothing at all in two designs out of three**: `display:
   contents` leaves no box, no row and no gap behind it, so its children stand
   in the body's own grid exactly as they stood before it existed. Only «صورة
   على الجنب» makes a column of it, because only there is there a column. */
.pcard__text {
    display: contents;
}

/* On the picture, where P-018 §3 puts it — and above the veil of design three
   so it is never dimmed with the photograph under it. */
.pcard__badge {
    position: absolute;
    z-index: 2;
    inset-block-start: 0.6rem;
    inset-inline-start: 0.6rem;
    padding: 0.15rem 0.7rem;
    border-radius: 999px;
    background: var(--primary);
    color: var(--on-primary);
    font-size: 0.8rem;
}

/* A project with no picture cannot be published, so this is the door nobody
   comes through — and a badge with nowhere to sit is still a badge to read. */
.pcard__badge--in-body {
    position: static;
}

.pcard__title-link {
    color: inherit;
    text-decoration: none;
}

.pcard__category {
    color: var(--text-quiet);
    font-size: 0.85rem;
}

.pcard__title {
    margin: 0;
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--headings);
}

.pcard__sentence {
    color: var(--text-quiet);
    font-size: 0.95rem;
}

.pcard__amounts {
    color: var(--text-quiet);
    font-size: 0.9rem;
}

/* ① · **حبرُ ما يقف على أرضيّة الكرت** — `DEFERRED` ٢٣، 12/08/2026.

   🔴 **ومحصورٌ بالكرت في المحدِّد نفسِه** ⛔ **لا في القاعدة التي فوقه** —
   **والعلّةُ واقعةٌ مقيسة**: **`--card-*` ألوانُ سطحِ الكرت وحدَه**، **وصنفٌ
   من أصنافه قد يُستعمل خارجَه** *(سطحُ القياس الثاني يرسم `.pcard__default`
   داخل صندوق التبرّع)* ⇒ **فحبرٌ مشتقٌّ من `--strip` يخرج أبيضَ على أبيض**.
   **رُئي في اللقطة قبل الإيداع** *([`T-093 §٤`])* — **وهي العلّةُ الجذريّةُ
   نفسُها**: **قيمةٌ تُشتقُّ من سطحٍ لا تلمسه.**

   ✅ **والافتراضُ هو ما في القاعدتين فوقه حرفًا** *(`--text-quiet` و`--headings`)*
   ⇒ ⛔ **صفرُ بكسلٍ يتحرّك في العشرة.** **وما يقف على أرضيّةٍ يملكها لا
   يُمَسّ**: **مبلغُ الخيار وجملتُه داخل مربّعٍ `--surface`، وجوابُ الضغط داخل
   `--ok-bg`** — **فحبرُها حبرُ سطحها.** */
.pcard .pcard__category,
.pcard .pcard__sentence,
.pcard .pcard__amounts,
.pcard .pcard__default-label {
    color: var(--card-quiet);
}

.pcard .pcard__title,
.pcard .pcard__default {
    color: var(--card-heading);
}

.pcard .pcard__button--quiet {
    background: var(--card-button-ground);
}

/* ---------- the progress bar, and its five shapes (ذ-١) ----------

   > # ✅ **انتقلت إلى ملفٍّ واحدٍ يقرؤه سطحان — 12/08/2026، [`P-083 §④`]**
   >
   > **وكانت هنا** — **`.pbar` وأخواتُها وهيئاتُها الخمسُ وخطوتا الحركة** —
   > **ويبقى ذكرُها ولا يُمحى** (RULES §٩/١).
   >
   > 🔑 **وعلّةُ النقل بنصّ المالك**: «**مصدرٌ واحد — تُقرأ القواعد من موضعها
   > الأصليّ** ⛔ **ولا نسخةَ ثانية**» — **فمعاينةُ اللوحة كانت تحمل نسخةً
   > ثانيةً منها في `app.css`.**
   >
   > ⇒ **وموضعُها اليوم** [`public/css/progress-shapes.css`](progress-shapes.css)
   > — **ورقةٌ تُربط قبل هذه في الموقع، وبعد `app.css` في اللوحة.**
   >
   > ⛔ **ولا إعلانَ تغيّر ولا قيمةَ تحرّكت بالنقل** — **سوى ما أمر به
   > [`P-083 §②`] في اللمعة**، **ومحدِّدُ المعاينة أُضيف إلى قاعدتَي الهيئة
   > الخامسة.** **والترتيبُ محفوظ**: **ما هو أخصُّ في هذه الورقة يبقى فوقها**
   > *(`.pcard--design-3 .pbar` أسفلَ هذا الملفّ)*. */

/* ---------- the giving, on the card itself (P-018) ---------- */

/* It spans the body's whole width whatever the design, so the buttons under it
   are the same buttons in all three. */
.pcard__give,
.pcard__answer {
    justify-self: stretch;
    width: 100%;
}

.pcard__answer {
    margin: 0;
    padding: 0.4rem 0.7rem;
    border: var(--border-width) solid var(--ok-border);
    border-radius: var(--radius-small);
    background: var(--ok-bg);
    color: var(--text);
    font-size: 0.9rem;
}

/* One amount, not several. The whole choice is pressable, and the tick stays in
   the page rather than being hidden: it is what a browser with no stylesheet
   still shows, and what says «chosen» to anybody reading with something other
   than his eyes. */
/* **One rule for the three designs and for both widths, and no design is
   excepted** — the owner's own words. The choices fill the card and divide it
   equally however many there are: one takes the whole width, two take halves,
   three and four take a row apiece on a wide screen.

   **And one thing outranks the division: the figure and its currency stay whole
   and readable.** That is what `--choice-floor` is — a floor under the width of
   a single choice, not a number of columns. `auto-fit` lays as many choices in
   a row as can each keep that floor and drops the rest to the next row; the
   tracks that stay are all `1fr`, so whatever ends up in a row is divided
   evenly. A readable choice over two rows beats four cramped ones —
   «الأولوية للقراءة لا للتناسق».

   So the phone does not get a different rule; it gets a bigger floor, because a
   quarter of a phone is not a readable width. Two to a row there, and four
   become two and two rather than three and an orphan.

   **The floor is a measurement, not a taste.** «1000 د.ك» on one line is 86px
   at the card's own size, and the cell's padding and borders are 17.6px — so a
   cell reads its figure whole at 103.6px, which is 6.5rem. Written any smaller
   and the figure tears away from its currency onto a second line; and the
   answer to that is never a smaller type, because the rule forbids it in the
   same breath: «أو يصغر عن حدّه». Measured in T-024. */
.pcard__choices {
    --choice-floor: 6.5rem;

    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(var(--choice-floor), 1fr));
    gap: 0.4rem;
    margin: 0 0 0.6rem;
    padding: 0;
    border: 0;
}

.pcard__choice {
    display: grid;
    gap: 0.2rem;
    justify-items: start;
    align-content: start;
    padding: 0.45rem 0.5rem;
    border: var(--border-width) solid var(--line-strong);
    border-radius: var(--radius-small);
    background: var(--surface);
    cursor: pointer;
}

.pcard__choice:has(input:checked) {
    border-color: var(--primary);
    box-shadow: inset 0 0 0 1px var(--primary);
}

.pcard__choice-amount {
    font-weight: 700;
    color: var(--headings);
}

/* Hidden until its own amount is chosen — the browser's own work and no script.
   Four sentences at once on a card this narrow is four sentences nobody reads,
   and the one that matters is the one he just chose. */
.pcard__choice-sentence {
    display: none;
    color: var(--text-quiet);
    font-size: 0.85rem;
}

.pcard__choice:has(input:checked) .pcard__choice-sentence {
    display: block;
}

/* No ready amounts: what the buttons will give, written out before anything is
   pressed. */
.pcard__default {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem;
    margin: 0 0 0.6rem;
    font-weight: 700;
    color: var(--headings);
}

.pcard__default-label {
    font-weight: 400;
    color: var(--text-quiet);
}

.pcard__buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.pcard__button {
    flex: 1 1 8rem;
    text-align: center;
}

/* The second is the quieter of the two: it keeps the visitor where he is, and
   the first is the one that takes him on.

   ① · **وأرضيّتُه محورٌ لا قيمةٌ مكتوبة داخلَ الكرت** — `DEFERRED` ٢٣:
   **شفّافٌ على سطحٍ عاديّ** *(وهي القيمةُ الباقيةُ هنا حرفًا)* · **ومصمتٌ
   `--surface` على سطحٍ ملوّن** *(القاعدةُ المحصورةُ بالكرت أعلاه)* ⇒ **فحبرُه
   `--text` صادقٌ في الحالين**، **وهو بعينه ما يفعله «صورة خلفية» بالزرِّ نفسِه
   أسفلَ هذا الملفّ.** */
.pcard__button--quiet {
    background: transparent;
    border-color: var(--line-strong);
    color: var(--text);
}

/* Design one: the picture above the writing. */
.pcard--design-1 {
    grid-template-columns: minmax(0, 1fr);
}

/* Design two: the picture beside the writing — the default, and the one shape
   that reads the same in a wide row and in a narrow column.

   **The picture is beside the writing and above nothing else.** It shared a row
   with the amounts until the owner saw what that costs: a row is as tall as the
   tallest thing in it, so every amount added to a project made the writing
   column taller, and a picture told to fill that column came out a tall sliver
   — «وحشة ولا تُقبل». The cure is the cause and not the mark: the giving leaves
   the column altogether.

   Two rows, then. The top one is the picture and the short writing beside it.
   The one under it is the whole width of the card: the amounts, then the two
   buttons. And the picture is square at the width of its own column — the
   square the owner uploaded — whatever stands under it, four amounts or one or
   none. The body itself is `display: contents` here, so its three pieces are
   placed by the card's grid rather than stacked inside a box that cannot span
   a column it does not own. */
.pcard--design-2 {
    grid-template-columns: minmax(0, 10rem) minmax(0, 1fr);
}

.pcard--design-2 .pcard__body {
    display: contents;
}

.pcard--design-2 .pcard__media {
    grid-column: 1;
    grid-row: 1;
    align-self: start;
}

/* The writing takes the look the body had — its grid, its gap, its padding —
   because it is standing in the body's place in this design. */
.pcard--design-2 .pcard__text {
    grid-column: 2;
    grid-row: 1;
    display: grid;
    gap: 0.45rem;
    justify-items: start;
    align-content: start;
    padding: calc(1rem * var(--space));
    min-width: 0;
}

/* With something under it, the writing gives up its own floor: what separates it
   from the giving becomes the same 0.45rem the other two designs leave there.

   What is left over when cards in a row are made the same height falls here too,
   between the writing and the giving — and that is where it should fall: the
   giving keeps its own foot at the card's floor, so **the buttons of every card
   in a row stand on one line** however much writing is above them. */
.pcard--design-2 .pcard__text:not(:last-child) {
    padding-block-end: 0.45rem;
}

/* The whole width of the card, under the picture and the writing both. The
   body's side padding comes back as a margin, since these are the card's own
   items here and not the body's. */
.pcard--design-2 .pcard__give,
.pcard--design-2 .pcard__answer {
    grid-column: 1 / -1;
    width: auto;
    margin-inline: calc(1rem * var(--space));
}

.pcard--design-2 .pcard__answer {
    margin-block-end: 0.45rem;
}

/* At the card's floor, not floating in the middle of what is left over. Cards
   in a row are made the same height by the row, and the space that leaves over
   has to fall somewhere; putting the giving at the end sends it above the
   giving instead of through it, **so the buttons of the cards in a row stand on
   one line** — measured, not assumed: they stood on three different lines
   before this rule. */
.pcard--design-2 .pcard__give {
    align-self: end;
    margin-block-end: calc(1rem * var(--space));
}

/* Design three: the writing over the dimmed picture. The veil sits between the
   two so the words stay readable whatever the picture is. */
.pcard--design-3 {
    grid-template-columns: minmax(0, 1fr);
    min-height: 16rem;
}

.pcard--design-3 .pcard__media {
    position: absolute;
    inset: 0;
}

/* ① · **وحدُّ تركيبةِ «دائري»** — `DEFERRED` ٢٣: **صورةُ هذا التصميم تملأ
   الكرتَ من حافّةٍ إلى حافّة، ولا نسبةَ لها** ⇒ **وقرصٌ منها بيضةٌ تترك أربعَ
   زوايا فارغة** ⛔ **فحافّتُها صفرٌ هنا**، **وهي قيمةُ النظام لا قيمةٌ
   تُخترع.** **والتصميمان الآخران يلبسان القرصَ كما أُمر.** */
.pcard--design-3 .pcard__image {
    height: 100%;
    aspect-ratio: auto;
    border-radius: 0;
}

.pcard__veil {
    position: absolute;
    inset: 0;
    background: var(--strip);
    opacity: 0.55;
}

.pcard--design-3 .pcard__body {
    align-self: end;
    color: var(--on-strip);
}

.pcard--design-3 .pcard__title,
.pcard--design-3 .pcard__sentence,
.pcard--design-3 .pcard__amounts,
.pcard--design-3 .pcard__category {
    color: var(--on-strip);
}

/* ① · **مجرى الشريط داخل الكرت يقرأ خطَّ الكرت** — `DEFERRED` ٢٣.
   **والافتراضُ `--line` حرفًا** *(وهي القيمةُ التي ترسمها `progress-shapes.css`)*
   ⇒ **صفرُ فرقٍ في العشرة** — **والملوَّنُ يقرأ `--strip-line` كما يقرؤها
   «صورة خلفية» أسفلَه.** ⚠️ **والترتيبُ مقصود**: **الأخصُّ موضوعًا أسفل، فلا
   يسبق العامُّ خاصَّه.** */
.pcard .pbar {
    background: var(--card-line);
}

.pcard--design-3 .pbar {
    background: var(--strip-line);
}

/* The writing of design three sits over a photograph, and a photograph is not a
   colour — so nothing here is left to the veil alone.

   The words the theme guarantees a pair for take `--on-strip`, which every theme
   defines against `--strip` and against nothing else. **And everything that is
   pressed takes a solid ground of its own**: a choice and a button are read at a
   glance and pressed by a finger, and neither can be asked to stand on whatever
   pixels happen to be behind it. */
.pcard--design-3 .pcard__choice,
.pcard--design-3 .pcard__answer {
    background: var(--surface);
    color: var(--text);
    border-color: var(--line-strong);
}

.pcard--design-3 .pcard__choice-amount {
    color: var(--headings);
}

/* The figure gets a ground of its own too. It is not pressed, but it is the one
   thing on the card a visitor reads as a number before he decides — and a
   number half-lost in a photograph is a number he has to squint at. */
.pcard--design-3 .pcard__default {
    padding: 0.3rem 0.6rem;
    border-radius: var(--radius-small);
    background: var(--surface);
    color: var(--headings);
}

.pcard--design-3 .pcard__default-label {
    color: var(--text-quiet);
}

.pcard--design-3 .pcard__button--quiet {
    background: var(--surface);
    color: var(--text);
    border-color: var(--line-strong);
}

/* ---------- the projects: the two listing pages ---------- */

.page__empty {
    color: var(--text-quiet);
}

/* The sub-categories, inside their parent's page. Two levels reach the menu
   and the third is reached from here — the owner's ruling. */
.category-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 calc(1.5rem * var(--space));
}

.category-bar__entry {
    display: inline-flex;
    padding: 0.35rem 0.9rem;
    border: var(--border-width) solid var(--line-strong);
    border-radius: 999px;
    color: inherit;
    text-decoration: none;
}

/* ---------- the projects: one project's page ---------- */

/* The five shapes draw the same ten blocks in the same order and differ in one
   thing: where the donation box sits. Three of them keep it in the flow, so
   they need no rule at all here — the page is one column and the box is a
   block in it, at the place the template put it. The two that put it in a side
   column are the two written below. */
.project {
    display: grid;
    gap: calc(1.5rem * var(--space));
    align-items: start;
}

.project__main {
    display: grid;
    gap: calc(1.25rem * var(--space));
    align-content: start;
    min-width: 0;
}

.project--shape-1,
.project--shape-2 {
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
}

.project__side {
    min-width: 0;
}

/* Shape one, and the single declaration that is the whole difference between
   it and shape two: the box stays in front of the eye however far the reading
   runs past it. CSS alone — there is no script on this site. */
.project--shape-1 .project__side {
    position: sticky;
    top: calc(1rem * var(--space));
}

.project__media {
    display: block;
}

.project__image {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius);
}

.project__head {
    display: grid;
    gap: 0.5rem;
    justify-items: start;
}

.project__badge {
    padding: 0.2rem 0.8rem;
    border-radius: 999px;
    background: var(--primary);
    color: var(--on-primary);
    font-size: 0.85rem;
}

.project__title {
    margin: 0;
    font-size: 1.9rem;
    line-height: 1.5;
    font-weight: 700;
    color: var(--headings);
}

.project__facts {
    margin: 0;
    color: var(--text-quiet);
}

.project__facts a {
    color: inherit;
}

.project__progress {
    display: grid;
    gap: 0.4rem;
}

.project__amounts {
    margin: 0;
    color: var(--text-quiet);
}

.project__lead {
    margin: 0;
    font-size: 1.1rem;
}

.project__body {
    display: grid;
    gap: calc(1rem * var(--space));
    max-width: var(--reading-width);
}

.project__paragraph {
    margin: 0;
}

.project__paragraph-image {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius);
}

.project__block {
    display: grid;
    gap: 0.6rem;
}

.project__countries {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.project__countries li {
    padding: 0.3rem 0.8rem;
    border: var(--border-width) solid var(--line);
    border-radius: 999px;
}

.project__stage {
    padding: calc(1rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.project__stage-title {
    margin: 0 0 0.4rem;
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--headings);
}

.project__stage-images {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: 0.6rem;
    margin: 0.6rem 0 0;
}

.project__stage-images img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius-small);
}

.project__share {
    margin: 0;
}

/* ---------- the projects: the donation box ---------- */

/* The running total is added up by this stylesheet and by nothing else. The
   counter is reset here, every chosen amount increments it by its own figure
   through a rule the page writes for itself, and the figure is read out of
   counter() below. No script runs anywhere on this site. */
.don {
    counter-reset: donation-total 0;
    display: grid;
    gap: 0.8rem;
    padding: calc(1rem * var(--space));
    border: var(--border-width-strong) solid var(--primary);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.don__heading {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--headings);
}

.don__shut {
    margin: 0;
    color: var(--text-quiet);
}

.don__answer {
    margin: 0;
    padding: 0.5rem 0.8rem;
    border: var(--border-width) solid var(--ok-border);
    border-radius: var(--radius-small);
    background: var(--ok-bg);
}

.don__form {
    display: grid;
    gap: 0.8rem;
}

.don__choices {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
    gap: 0.5rem;
}

/* A whole choice is pressable, not a small square beside a word. The tick
   itself stays in the page rather than being hidden: it is what a browser with
   no stylesheet at all still shows, and it is what says «chosen» to anybody
   reading the page with something other than his eyes. */
.don__choice {
    display: grid;
    gap: 0.25rem;
    justify-items: start;
    padding: 0.6rem;
    border: var(--border-width) solid var(--line-strong);
    border-radius: var(--radius-small);
    cursor: pointer;
}

.don__choice:has(input:checked) {
    border-color: var(--primary);
    box-shadow: inset 0 0 0 1px var(--primary);
}

.don__amount {
    font-weight: 700;
    color: var(--headings);
}

.don__sentence {
    color: var(--text-quiet);
    font-size: 0.9rem;
}

.don__section {
    margin: 0;
    padding: 0.6rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius-small);
}

.don__section-name {
    padding: 0 0.4rem;
    font-weight: 700;
    color: var(--headings);
}

.don__free,
.don__field {
    display: grid;
    gap: 0.3rem;
}

.don__label {
    color: var(--text-quiet);
}

.don__required {
    color: var(--error);
}

.don__free-row {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.don__hint {
    color: var(--text-quiet);
    font-size: 0.9rem;
}

.don__option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
}

.don__donor {
    display: grid;
    gap: 0.6rem;
}

.don__total {
    margin: 0;
    font-weight: 700;
    color: var(--headings);
}

/* The counter, read out. Anything ticked anywhere in the box has already
   incremented it by the time this element is reached, because a counter is
   read in document order and the total stands after the choices. */
.don__total-number::after {
    content: counter(donation-total);
}

/* A typed free amount cannot enter a CSS counter — a counter reads no value
   from a field. So the figure steps aside for the owner's own sentence the
   moment anything is typed, rather than going on showing a total that is
   missing what he just wrote. `:placeholder-shown` is what tells an empty box
   from a filled one with no script at all. */
.don__total-note {
    display: none;
    font-weight: 400;
    color: var(--text-quiet);
}

.don__total-note--always {
    display: inline;
}

.don:has(.don__free-input:not(:placeholder-shown)) .don__total-label,
.don:has(.don__free-input:not(:placeholder-shown)) .don__total-number,
.don:has(.don__free-input:not(:placeholder-shown)) .don__total-symbol {
    display: none;
}

.don:has(.don__free-input:not(:placeholder-shown)) .don__total-note {
    display: inline;
}

/* And when the owner never wrote that sentence, the whole line steps aside
   instead: an empty value is not drawn and leaves no gap. */
.don:has(.don__free-input:not(:placeholder-shown)) .don__total--no-note {
    display: none;
}

.don__buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* ---------- the projects: the video ---------- */

.video-poster {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 16rem;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--line);
}

.video-poster__media {
    position: absolute;
    inset: 0;
}

.video-poster__image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.video-poster__veil {
    position: absolute;
    inset: 0;
    background: var(--strip);
    opacity: 0.45;
}

/* ④ · **زرُّ اليوتيوب صار `.file-button` كأخيه** — 12/08/2026، بأمر المالك في
   [`P-085 §④`]: «**يُوحَّدان مقاسًا وحشوةً من مصدرٍ واحد** ⇒ **فلا يفترقان غدًا
   بتعديلِ أحدهما**».

   > ~~**وكانت هنا قاعدةٌ خاصّةٌ تكتب له تسعةَ إعلانات**~~ — **وتبقى مذكورةً ولا
   > تُمحى** *(RULES §٩/١)*:
   >
   > ~~`display:inline-flex` · `align-items:center` · `padding:0.6rem 1.4rem` ·
   > `border:var(--border-width) solid var(--primary)` · `border-radius:var(--radius)` ·
   > `background:var(--primary)` · `color:var(--on-primary)` · `text-decoration:none` ·
   > `font-weight:700`~~
   >
   > 🔴 **وثمانيةٌ منها نسخةٌ حرفيّةٌ من `.file-button`** ⇒ **فالافتراقُ كان في
   > الحشوة وحدَها، والنسخُ هو ما جعله ممكنًا.**

   ✅ **والمفرداتُ اليومَ من `.file-button`** *(القالبُ يلبسه الصنف)*، **والحشوةُ
   والخطُّ في القاعدة المشتركة أسفلَ الورقة** ⇒ ⛔ **وصفرُ إعلانٍ خاصٍّ بهذا الزرّ
   هنا.** */

/* ---------- the uploaded video, played where it stands ---------- */

/* **The ratio is the whole of the no-jump guarantee, and it is written here
   rather than measured anywhere.** The box holds sixteen by nine before the
   press and after it: the poster fills it, and the video fills the same box
   whatever its own shape is. Nothing below the box can move, because the box
   never changes height.

   That is also why an uploaded video is asked for a poster at all: without one
   the browser would draw an empty black rectangle until the first frame
   arrived, and the visitor would have nothing to press. */
.video-box {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--radius);
    border: var(--border-width) solid var(--primary);
    background: var(--strip);
}

/* ذ-٢ · **الغطاءُ الذي يحمل زرَّ التشغيل بلون الجمعية** — 12/08/2026.

   🔴 **ولا وجودَ له بلا جافاسكربت**: الخادمُ يكتبه ومعه `hidden`، والسكربتُ
   وحدَه ينزعها ⇒ **فمن أطفأ السكربتَ لا يرى غطاءً أصلًا، ويجد مشغّلَ المتصفّح
   كما كان.** والقاعدةُ هنا لا تُلغي `hidden` ولا تعاندها — `[hidden]` تبقى
   على أصلها في الورقة. */
.video-box__cover {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    cursor: pointer;
}

/* 🔴 **وهذا السطرُ هو الحدُّ الثاني نفسُه، مكتوبًا.** `display` من ورقةِ مؤلِّفٍ
   تغلب `[hidden]` التي في ورقة المتصفّح ⇒ **فبلا هذا السطر يُرسَم الغطاءُ على
   من أطفأ السكربتَ ويحجب المشغّل** — وهو عينُ ما نهى عنه أمرُ المالك. */
.video-box__cover[hidden] {
    display: none;
}

.video-box__cover-image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* الغلافُ يُحتوى لا يُقصّ — هي قاعدةُ المشغّل تحته نفسُها، فلا تختلف
       الصورةُ قبل الدوسة عنها بعدها. */
    object-fit: contain;
    background: var(--strip);
}

/* ~~الحجابُ نفسُه الذي يحمله غلافُ اليوتيوب — لونًا وشفافيةً ⛔ ولا قيمةَ
   جديدة.~~

   > # ✅ **خُفِّف — 12/08/2026، بأمر المالك في [`P-082 §⑥`]**
   >
   > **والمشطوبُ فوقه يبقى مقروءًا ولا يُمحى** (RULES §٩/١) — **واللونُ هو
   > اللون، والذي تغيّر الشفافيةُ وحدَها**: <span dir="ltr">0.45</span> ⇐
   > <span dir="ltr">0.35</span>.
   >
   > 🔴 **وعلّتُه بنصّ المالك**: «**الغلاف يظهر أدكن ممّا رفعه المالك**» —
   > **وقالها الفنّانُ قبله**: «**صورةٌ اختارها المالكُ بعناية تُعرض معتمةً حتى
   > يُضغط عليها**» *([`R-092/م١ §٦`])*.
   >
   > ⛔ **ولم يُخترع الرقم**: <span dir="ltr">0.35</span> **قيمةٌ قائمةٌ في
   > النظام** — `SiteTheme::variableLines()` **تمزج بها `--line-strong`،
   > وتحملها هذه الورقةُ في `impact-map-beat`** — **وهي أقربُ قيمةٍ دون
   > <span dir="ltr">0.45</span> في مفردات النظام** ⇒ **أقلُّ تخفيفٍ متاحٍ في
   > الاتجاه المأمور به.**
   >
   > ✅ **والزرُّ فوقه لم يتغيّر حرفًا**: **مِلْؤُه غيرُ شفّاف** ⇒ **فحدُّ
   > «حبر/زرّ» <span dir="ltr">4.5</span>** *(`PALETTE_CONTRAST_FLOORS`)*
   > **لا يقرأ الحجابَ أصلًا — مقيسٌ متطابقًا قبلَه وبعدَه على الثمانِ
   > والعشرين.**
   >
   > ⚠️ **وما لا يشتريه هذا الحجابُ ولا الذي قبله، مقيسًا لا مظنونًا**:
   > **تمييزُ مِلء الزرِّ عن الغلاف خلفه** — **حدُّ «جمعية/صفحة»
   > <span dir="ltr">3.32</span>** — **كان دون الحدِّ على الثمانِ والعشرين
   > جميعًا عند <span dir="ltr">0.45</span> نفسِها** ⇒ **فليس الحجابُ هو ما
   > يشتريه، وتخفيفُه لا يكسر وعدًا كان قائمًا** *(الأرقامُ في [`T-086 §٦`])*.
   >
   > ⛔ **ولم يُمَسّ `.video-poster__veil`** — **غلافُ اليوتيوب خارج هذا البند
   > نصًّا** *(«غلاف الفيديو تحت الحجاب» — المرفوعُ من مكتبة الوسائط)*. */
.video-box__veil {
    position: absolute;
    inset: 0;
    background: var(--strip);
    opacity: 0.35;
}

/* ① · **الزرُّ يحمل فاصلَه معه** — 12/08/2026، بأمر المالك في [`P-083 §①`].
       الأمرُ بنصّه: «**حدٌّ أو حلقةٌ أو ظلٌّ صلبٌ يفصل مِلأه عمّا خلفه، لونه
       مشتقٌّ من الثيم بمعادلة قائمة** ⛔ **لا مكتوبًا بيدك** ⛔ **ولا لونًا
       ثابتًا لكل الثيمات**».

   ## 🔴 العلّةُ الجذرية — **ولمَ لا يُبلَغ الحدُّ بحجابٍ أبدًا**

   **الغلافُ صورةٌ حرّةٌ ترفعها كلُّ جمعية** ⇒ **فلونُ الزرِّ قد يقع على لونٍ
   مثلِه بالضبط** — **وتباينُ لونٍ ثابتٍ مع صورةٍ مجهولةٍ غيرُ مقدورٍ عليه، لا
   بتعتيمٍ ولا بحجاب** *(مقيسٌ في [`T-086 §٦/٣`]: حدُّ «جمعية/صفحة»
   <span dir="ltr">3.32</span> **كان مكسورًا على الثمانِ والعشرين عند
   <span dir="ltr">0.45</span> وعند <span dir="ltr">0.35</span> سواء)*.

   ## ✅ **والحلُّ أنّ الفاصلَ داخلَ الزرِّ لا خارجَه**

   **حلقتان متلاصقتان**: **الداخلةُ `--on-primary` والخارجةُ `--primary`** ⇒
   **وبينهما حدٌّ تباينُه هو حدُّ «حبر/زرّ» بعينه** — **أضعفُه على الثمانِ
   والعشرين <span dir="ltr">4.5267</span>** *(`warm_maroon`)* — 🔑 **وهو حدٌّ
   **لا تبلغه الصورةُ خلفَه مهما كان لونُها**، **لأنّ طرفَيه كليهما من الثيم.**
   ⇒ **فالزرُّ يُرى محدودًا على غلافٍ أبيضَ وعلى غلافٍ أسودَ سواء** *(مقيسٌ من
   اللقطتين في [`T-087 §١/٣`])*.

   ⛔ **ولا لونَ كُتب**: `--primary` **اختيارُ المالك**، **و`--on-primary`
   مشتقٌّ منه بـ`SiteTheme::readableInkOn()`** — **معادلةٌ قائمةٌ منذ بُني
   الثيم** ⇒ **واللونان يتغيّران مع كلِّ تركيبةٍ من الثمانِ والعشرين.**

   ⛔ **ولم تُمَسّ الصورةُ بحرف**: **لا تعتيمَ زِيد، ولا حجابَ ثُقِّل، ولا
   وضوحَ نقص** — **العلاجُ كلُّه في الزرِّ نفسِه.**

   ⚠️ **والعرضان من مفردات الشكل** ⛔ **لا رقمَ جديد**: **الداخلةُ عرضُ حدِّ
   `.file-button` نفسِه `--border-width`** — **لم يتغيّر منه إلا اللون** —
   **والخارجةُ `--border-width-strong`، وهي «الحدُّ الأثقل» في لغة كلِّ شكل**
   *(<span dir="ltr">1px</span> إلى <span dir="ltr">3px</span> بحسب الشكل)*.

   ## ✅ **وزرُّ اليوتيوب دخل القاعدةَ نفسَها — 12/08/2026، [`P-084 §①`]**

   ~~**وكان `.video-box__play` وحدَه في هذه القاعدة**~~ — **ويبقى مكتوبًا ولا
   يُمحى** *(RULES §٩/١)*. 🔴 **وعلّةُ ضمِّه أنّ العلّةَ واحدة**:
   **`.video-poster__play` يقع على غلافٍ حرٍّ كذلك** — **غلافُ المشروع تحت
   حجابٍ <span dir="ltr">0.45</span>** — ⇒ **ومِلؤه كان يلمس الصورةَ مباشرة**
   *(مقيسٌ في [`T-088 §١/١`]: **<span dir="ltr">27</span> من
   <span dir="ltr">28</span> تحت حدِّ <span dir="ltr">3.32</span> على غلافٍ
   أبيض، و<span dir="ltr">10</span> على أسود)*.

   🔑 **ومصدرُهما واحدٌ بعد اليوم** ⛔ **لا قاعدتان تتفرّقان غدًا بتعديل
   إحداهما** — **يحرسه `VideoPlayButtonSeparatorGuardTest`.** ⚠️ **والمشترَك
   هو الفاصلُ وحدَه** — **الحلقتان والعلوُّ فوق الحجاب** — ⛔ **لا المقاسُ ولا
   الحشوةُ ولا الخطّ**: **زرُّ اليوتيوب رابطٌ أكبرُ حشوةً، والمرفوعُ زرُّ
   `.file-button`** ⇒ **وتوحيدُ المقاس تغييرُ ما يُرى ولم يُؤمَر به.** */
/* ## ✅ **وصار المقاسُ هنا كذلك — 12/08/2026، [`P-085 §④`]**

   **الأمرُ بنصّه**: «**يُوحَّدان مقاسًا وحشوةً من مصدرٍ واحد** · **والمأخوذُ
   قيمةٌ من القائمتين** ⛔ **ولا مقاسَ جديدٌ يُخترع — ويُعلَن أيُّهما أُخذ ولمَ**».

   🔑 **والمأخوذُ حشوةُ زرِّ اليوتيوب** *(<span dir="ltr">0.6rem 1.4rem</span>)*
   **لا حشوةُ `.file-button`** *(<span dir="ltr">0.4rem 0.9rem</span>)* — **وهي
   قيمةٌ قائمةٌ في الورقة منذ بُنيت الشريحة** ⛔ **لم تُخترع اليوم.**

   **وعلّةُ اختيار الأكبر مقيسةٌ لا ذوقيّة**: **الأصغرُ يُنقص هدفَ لمسٍ قائمًا**
   — **ارتفاعُ الزرِّ يهبط من <span dir="ltr">52</span> إلى
   <span dir="ltr">45</span> بكسلًا على أضعف شكل** — **وكلاهما دون
   <span dir="ltr">44</span> نقطةً بعد قسمةِ الكثافة** ⇒ **فالأكبرُ يرفع واحدًا
   ولا يُنزل أحدًا، والأصغرُ يُنزل الاثنين** · ⚠️ **وهذان زرّان يقعان على صورةٍ
   حرّةٍ ويُضغطان بالإبهام على الهاتف** *(RULES §١٠: «ولا صفحة تُسلَّم دون أن
   تُجرَّب على مقاس الهاتف»)*.

   ⛔ **و`.file-button` نفسُها لم تُمَسّ**: **حشوتُها كما هي في كلِّ زرٍّ آخرَ في
   الموقع** — **والزيادةُ هنا وحدَها، على زرَّي الفيديو معًا** *(مقيسٌ: صفرُ
   بكسلٍ تغيّر في اللقطات المرجعية الثمانَ عشرةَ للأشكال)*. */
.video-box__play,
.video-poster__play {
    position: relative;
    z-index: 1;
    padding: 0.6rem 1.4rem;
    border-color: var(--on-primary);
    box-shadow: 0 0 0 var(--border-width-strong) var(--primary);
    font-weight: 700;
}

.video-box__player {
    display: block;
    width: 100%;
    height: 100%;
    /* Contain and not cover: a video is not decoration and must not be cropped
       to fit a shape somebody else chose. The bars around it are the box's own
       colour, which is the theme's. */
    object-fit: contain;
    background: var(--strip);
}

/* The frame stands over the page on the one visit that asked for it. It is a
   whole page load and not a panel a script opened, so there is nothing to
   close and reopen: «إغلاق» is a link back to the project's own address. */
.video-overlay {
    position: fixed;
    inset: 0;
    z-index: 50;
    display: grid;
    place-items: center;
    padding: 1rem;
    background: var(--page-veil);
}

.video-overlay__panel {
    width: min(64rem, 100%);
    display: grid;
    gap: 0.6rem;
}

.video-overlay__frame {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--strip);
}

.video-overlay__frame iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

.video-overlay__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
}

/* ---------- the basket ----------

   Everything on this page is HTML the browser already knows: forms, buttons and
   one <details> for the question before emptying. There is no script here and
   no place for one — every action is a press, a POST and a redirect. */

.cart {
    display: grid;
    gap: 1.2rem;
    max-width: 68rem;
    margin-inline: auto;
}

/* Two columns, and the markup is written in the order of a phone: the projects,
   the contact details, the total, the button. The wide screen lifts the contact
   details into the second column by naming their cell and holds everything else
   to the first — so the reading order and the seeing order are one thing written
   once, and a screen reader meets what an eye meets.

   The rest name their column too. Without that, auto-placement would slide the
   total up beside the projects the moment the contact details took the cell it
   would otherwise have fallen into. */
.cart__layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
    align-items: start;
    gap: 1.2rem;
}

.cart__blocks {
    display: grid;
    gap: 1.2rem;
    grid-column: 1;
    grid-row: 1;
}

.cart__rule,
.cart__total-place,
.cart__pay,
.cart__ways {
    grid-column: 1;
}

/* The line that closes the basket and opens the paying. */
.cart__rule {
    width: 100%;
    height: 0;
    margin: 0;
    border: 0;
    border-top: var(--border-width) solid var(--line);
}

.cart__heading {
    margin: 0;
    color: var(--headings);
}

.cart__notice-name {
    font-weight: 700;
}

.cart__empty {
    margin: 0;
    color: var(--text-quiet);
}

.cart__block {
    display: grid;
    gap: 0.8rem;
    padding: 1rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.cart__block-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.6rem;
}

.cart__block-title {
    margin: 0;
    font-size: 1.15rem;
    color: var(--headings);
}

.cart__block-title a {
    color: inherit;
    text-decoration: none;
}

/* `.cart__block-number` stood here with it until the project's number left every
   page a visitor sees — and a rule for a class nothing wears is a loose end. */
.cart__line-note {
    color: var(--text-quiet);
    font-size: 0.9rem;
}

.cart__zakat {
    padding: 0.15rem 0.6rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    color: var(--text-quiet);
    font-size: 0.85rem;
}

.cart__lines {
    display: grid;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* What it is · what it costs · the button that takes it out on its own. Every
   line goes by itself: a line that could only be removed by taking the whole
   project out is a line the visitor is stuck with. */
.cart__line {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 0.6rem;
    padding-bottom: 0.5rem;
    border-bottom: var(--border-width) solid var(--line);
}

.cart__line:last-child {
    padding-bottom: 0;
    border-bottom: 0;
}

.cart__line-what {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem;
}

.cart__line-section {
    font-weight: 700;
    color: var(--headings);
}

.cart__line-amount {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    white-space: nowrap;
}

.cart__amount-input {
    width: 7rem;
    padding: 0.4rem 0.6rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--page);
    color: var(--text);
    font: inherit;
}

.cart__hint {
    margin: 0;
    color: var(--text-quiet);
    font-size: 0.9rem;
}

.cart__field {
    display: grid;
    gap: 0.3rem;
}

.cart__label {
    color: var(--text-quiet);
}

.cart__required {
    color: var(--error);
}

.cart__field input,
.cart__field textarea {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--page);
    color: var(--text);
    font: inherit;
}

.cart__block-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
}

/* The two quiet ones stand side by side under the paying button, and the row
   is aligned to its top so the question before emptying opens downwards
   without dragging the button beside it along with it. */
.cart__ways {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0.6rem;
}

/* Worn by a button and by a link alike, because what a control looks like is
   about its weight on the page and not about whether it posts or goes. */
.cart__quiet-button {
    display: inline-block;
    padding: 0.4rem 0.8rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-quiet);
    font: inherit;
    font-size: 0.95rem;
    text-decoration: none;
    cursor: pointer;
}

/* Alone, across the column, with nothing beside it — the one thing on this page
   a visitor came to press. */
.cart__pay-button {
    width: 100%;
    padding-block: 0.9rem;
    font-size: 1.1rem;
    font-weight: 700;
}

/* Beside the projects and out of the road between the basket and the paying
   button. It has no button of its own: what is written here rides with the
   press that uses it. */
.cart__donor {
    display: grid;
    gap: 0.8rem;
    padding: 1rem;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    grid-column: 2;
    grid-row: 1;
}

.cart__donor-heading {
    margin: 0;
    font-size: 1.1rem;
    color: var(--headings);
}

/* The total is printed by the server, exact, fractions and all — this page has
   no counter to keep and nothing on it changes without a round trip. */
.cart__total {
    margin: 0;
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--headings);
}

.cart__total-label {
    font-weight: 400;
    color: var(--text-quiet);
}

/* The one moment the figure steps aside: while an amount above it is being
   typed. At that instant the printed number is not the number, and the owner's
   own sentence says so. It is CSS's whole part in this page, and it does
   nothing at all when he has written no sentence — a number hidden for nothing
   would be worse than a number a second out of date. */
.cart__total-note {
    display: none;
    font-size: 1rem;
    font-weight: 400;
    color: var(--text-quiet);
}

.cart:has(.cart__amount-input:focus) .cart__total--has-note .cart__total-figure {
    display: none;
}

.cart:has(.cart__amount-input:focus) .cart__total--has-note .cart__total-note {
    display: inline;
}

.cart__empty-ask summary {
    display: inline-block;
}

.cart__empty-ask form {
    display: grid;
    gap: 0.5rem;
    justify-items: start;
    margin-top: 0.6rem;
}

/* ---------- the projects on a phone ---------- */

@media (max-width: 48rem) {
    /* One column, and the markup already stands in the right order: the
       projects, the contact details, the total, the button. Every cell named
       for the wide screen is unnamed here and falls back to where it was
       written. */
    .cart__layout {
        grid-template-columns: minmax(0, 1fr);
    }

    .cart__blocks,
    .cart__donor {
        grid-column: 1;
        grid-row: auto;
    }

    /* The basket's lines stack: what it is, then what it costs beside the
       button that removes it. A three-column row on a phone squeezes an Arabic
       sentence into a column two words wide. */
    .cart__line {
        grid-template-columns: minmax(0, 1fr) auto;
    }

    .cart__line-what {
        grid-column: 1 / -1;
    }

    /* One column for the cards, and one for the page. The five shapes all
       become the same single column here, and the box keeps the place in the
       order its shape gave it — which is the whole of what a shape means once
       there is no second column to put anything in. */
    .pcards {
        grid-template-columns: minmax(0, 1fr);
    }

    .pcard--design-2 {
        grid-template-columns: minmax(0, 7rem) minmax(0, 1fr);
    }

    /* **Not a different rule — a bigger floor.** A quarter of a phone is not a
       width a figure can be read in, so two to a row: three become two and one,
       four become two and two. The rule itself is the one written above, and it
       is the same rule for the three designs here as there. */
    .pcard__choices {
        --choice-floor: 8rem;
    }

    .project--shape-1,
    .project--shape-2 {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Sticky in one column would pin the box over the reading rather than
       beside it. */
    .project--shape-1 .project__side {
        position: static;
    }

    .project__title {
        font-size: 1.5rem;
    }
}


/* ---------- the impact map (stage 3) ---------- */

/* Not one colour value below. Every rule here reads a theme variable, so the map
   follows a palette that is added years from now without this file being opened
   — and a guard in the tests fails if a colour value ever appears in it, in the
   map's own asset, or in its templates.

   The land is the theme's quiet neutral, the sea is the page itself, and the
   working countries and their pins are the theme's own primary. */

.impact-map {
    display: block;
    margin: 0;
    position: relative;
}

.impact-map__stage {
    width: 100%;
}

.impact-map__svg {
    display: block;
    width: 100%;
    height: auto;
    /* The map never leaves its own box, however far it is zoomed in. */
    overflow: hidden;
    border-radius: var(--radius);
    border: var(--border-width) solid var(--line);
    touch-action: none;
    cursor: grab;
}

.impact-map__svg:active { cursor: grabbing; }

/* A globe is square, so left at the page's full width it is as tall as the page
   is wide and pushes everything under it off the screen. It is held to a size a
   reader meets whole, and centred in its own box. The two flat shapes above are
   two to one and need no such holding. */
.impact-map--shape-4 .impact-map__svg,
.impact-map--shape-5 .impact-map__svg {
    max-width: min(100%, 620px);
    margin-inline: auto;
}

.impact-map__sea {
    fill: var(--page);
    stroke: var(--line);
    stroke-width: 1;
}

.impact-map__land {
    fill: var(--surface);
    stroke: var(--line-strong);
    stroke-width: 0.4;
    vector-effect: non-scaling-stroke;
}

.impact-map__country--working .impact-map__land {
    fill: var(--primary);
    stroke: var(--primary);
}

/* The name of a country that is not a working one. Hidden until the map is
   zoomed in or the pointer is on the country — the whole world's names at once
   is a crowd nobody can read. */
.impact-map__name {
    fill: var(--text-quiet);
    font-size: 11px;
    text-anchor: middle;
    dominant-baseline: middle;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition);
}

.impact-map--zoomed .impact-map__name { opacity: 1; }

.impact-map__country:hover .impact-map__name { opacity: 1; }

/* The name of a working country is always on the map, by the owner's order. */
.impact-map__pin-name {
    fill: var(--headings);
    font-size: 13px;
    font-weight: 700;
    text-anchor: middle;
    dominant-baseline: middle;
    transform: translateY(-14px);
    pointer-events: none;
    paint-order: stroke;
    stroke: var(--page);
    stroke-width: 3;
}

/* The pin. One colour for every country — no scale by how much work was done —
   and one size, whatever the zoom: its radius is an attribute the drawing sets
   once and never multiplies. */
.impact-map__pin {
    fill: var(--primary);
    stroke: var(--page);
    stroke-width: 2;
    animation: impact-map-beat 1.8s ease-in-out infinite;
    transform-box: fill-box;
    transform-origin: center;
}

.impact-map__pin-hit {
    fill: var(--page);
    fill-opacity: 0;
    cursor: pointer;
}

.impact-map__pin-hit:focus-visible {
    outline: var(--border-width-strong) solid var(--primary);
    outline-offset: 2px;
}

/* The beat: it lights and it dims, and it is CSS in all five shapes — the globe
   included — so nothing about it waits for a script. */
@keyframes impact-map-beat {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}

/* A pin on the far side of a globe goes behind the world with its country. */
.impact-map__pin-group--behind { display: none; }

/* The written list: the page when nothing draws, and where the drawing reads
   what it draws. It steps aside the moment a map is standing. */
.impact-map__list {
    list-style: none;
    margin: calc(16px * var(--space)) 0 0;
    padding: 0;
    display: grid;
    gap: calc(10px * var(--space));
}

.impact-map--drawn .impact-map__list { display: none; }

.impact-map__entry {
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius-small);
    padding: calc(10px * var(--space)) calc(14px * var(--space));
    background: var(--surface);
}

.impact-map__entry-name {
    display: block;
    font-weight: 700;
    color: var(--headings);
}

.impact-map__entry-figures {
    display: flex;
    flex-wrap: wrap;
    gap: calc(6px * var(--space)) calc(16px * var(--space));
    color: var(--text-quiet);
}

.impact-map__entry-note,
.impact-map__entry-button {
    display: block;
    margin-top: 6px;
}

.impact-map__entry-button { color: var(--primary); }

/* The country's window. Its two shapes differ in how the three figures sit and
   in nothing else: the same window, the same fields, the same words. */
.impact-map__window {
    position: absolute;
    inset-inline-end: calc(12px * var(--space));
    inset-block-start: calc(12px * var(--space));
    max-width: 320px;
    background: var(--page);
    border: var(--border-width) solid var(--line-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow-pop);
    padding: calc(14px * var(--space));
    z-index: 2;
}

.impact-map__window[hidden] { display: none; }

.impact-map__window-close {
    float: inline-start;
    background: none;
    border: 0;
    color: var(--text-quiet);
    font-size: 1.4em;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}

.impact-map__window-name {
    margin: 0 0 calc(10px * var(--space));
    color: var(--headings);
}

.impact-map__figures { margin: 0; }

.impact-map__figure { margin: 0; }

.impact-map__figure-value {
    font-weight: 700;
    color: var(--primary);
}

.impact-map__figure-label { color: var(--text-quiet); }

/* Shape one: the three figures in a row — the short one. */
.impact-map--window-1 .impact-map__figures {
    display: flex;
    gap: calc(14px * var(--space));
    flex-wrap: wrap;
}

.impact-map--window-1 .impact-map__figure {
    display: flex;
    flex-direction: column;
    font-size: 0.9em;
}

/* Shape two: every figure on a line of its own with its mark and its full name
   — the one that carries long figures and long names. */
.impact-map--window-2 .impact-map__figures {
    display: grid;
    gap: calc(8px * var(--space));
}

.impact-map--window-2 .impact-map__figure {
    display: flex;
    align-items: baseline;
    gap: 8px;
    border-block-end: var(--border-width) solid var(--line);
    padding-block-end: calc(6px * var(--space));
}

.impact-map--window-2 .impact-map__figure::before {
    content: "\2022";
    color: var(--primary);
}

.impact-map__window-note {
    margin: calc(10px * var(--space)) 0 0;
    color: var(--text);
    /* The one thing a written line is allowed to do to itself: a new line the
       owner left is honoured. No tag of his ever runs — the text is printed as
       text and this is the whole of the formatting he controls. */
    white-space: pre-line;
}

.impact-map__window-note[hidden] { display: none; }

.impact-map__window-button {
    display: inline-block;
    margin-top: calc(10px * var(--space));
    background: var(--primary);
    color: var(--on-primary);
    border-radius: var(--radius-small);
    padding: 8px 16px;
    text-decoration: none;
}

.impact-map__window-button[hidden] { display: none; }

/* The sentence under an empty map. */
.impact-map__empty {
    margin: calc(14px * var(--space)) 0 0;
    text-align: center;
    color: var(--text-quiet);
    white-space: pre-line;
}

.impact-map-page__lead { white-space: pre-line; }

/* The totals row: one shape, four cells, and every figure in it the sum of what
   the owner typed. */
.impact-map-totals {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: calc(12px * var(--space));
    margin: calc(20px * var(--space)) 0 0;
    padding: calc(16px * var(--space));
    background: var(--surface);
    border-radius: var(--radius);
    border: var(--border-width) solid var(--line);
}

/* An ordinary block, so the figure and its currency flow together on one line
   the way words do, and the name of the cell is put on a line of its own. As a
   column of three the currency sat alone between a figure and its name and read
   like a third fact of its own. */
.impact-map-totals__cell {
    margin: 0;
    text-align: center;
}

.impact-map-totals__value {
    font-size: 1.6em;
    font-weight: 700;
    color: var(--primary);
}

.impact-map-totals__currency { color: var(--primary); }

.impact-map-totals__label {
    display: block;
    margin-top: 4px;
    color: var(--text-quiet);
}

@media (max-width: 640px) {
    .impact-map-totals { grid-template-columns: repeat(2, 1fr); }

    .impact-map__window {
        position: static;
        max-width: none;
        margin-top: calc(12px * var(--space));
    }
}


/* ---------- the window over the home page (stage 3) ---------- */

/* **Not one line of script, and not one colour value.** The delay is an
   animation given its seconds by the template; the closing is the checkbox
   below, read with `:has()` the way the slider's dots are read; and every
   colour is the theme's own.

   The checkbox is the thing a keyboard reaches. It is not `display: none` —
   that would take it off the focus order and out of a screen reader — it is
   moved out of sight and kept reachable, and its label carries the word. */
.home-popup__switch {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.home-popup {
    position: fixed;
    inset: 0;
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: calc(16px * var(--space));
    background: var(--page-veil);

    /* Shut and out of the way until its own moment. `visibility` and not
       `display`, so the animation has something to animate to; and
       `pointer-events` so nothing under it is caught while it is not there. */
    visibility: hidden;
    opacity: 0;
    pointer-events: none;

    animation: home-popup-open 0.35s ease-out var(--popup-delay, 3s) forwards;
}

/* The press. `:has()` is what carries it, and it is already what the slider's
   dots and the projects' cards use, so nothing new is asked of the browser. */
body:has(.home-popup__switch:checked) .home-popup {
    animation: none;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
}

@keyframes home-popup-open {
    from {
        visibility: visible;
        opacity: 0;
        transform: translateY(12px);
    }
    to {
        visibility: visible;
        opacity: 1;
        transform: translateY(0);
        pointer-events: auto;
    }
}

/* The same arrival with nothing moving: it is simply there when its moment
   comes. A delay is not motion, so the window still waits its seconds. */
@keyframes home-popup-appear {
    from {
        visibility: visible;
        opacity: 1;
    }
    to {
        visibility: visible;
        opacity: 1;
        pointer-events: auto;
    }
}

.home-popup__box {
    position: relative;
    max-width: 560px;
    width: 100%;
    max-height: 90vh;
    overflow-y: auto;
    background: var(--page);
    border: var(--border-width) solid var(--line-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow-pop);
    padding: calc(24px * var(--space));
}

.home-popup__close {
    position: absolute;
    inset-inline-start: calc(12px * var(--space));
    inset-block-start: calc(12px * var(--space));
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    color: var(--text-quiet);
    font-size: 1.1em;
    line-height: 1;
    padding: 6px 10px;
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius-small);
    background: var(--surface);
}

.home-popup__close-word { font-size: 0.8em; }

/* The keyboard's own answer: focus lands on the hidden checkbox, and the ring
   is drawn around the word it belongs to so a hand can see where it is. */
.home-popup__switch:focus-visible ~ .home-popup .home-popup__close {
    outline: var(--border-width-strong) solid var(--primary);
    outline-offset: 2px;
}

.home-popup__image {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius-small);
}

.home-popup__title {
    margin: 0 0 calc(10px * var(--space));
    color: var(--headings);
}

.home-popup__text {
    margin: 0;
    color: var(--text);
    /* The new line the owner left is honoured, and it is the whole of the
       formatting he controls: what he writes is printed as text. */
    white-space: pre-line;
}

.home-popup__button {
    display: inline-block;
    margin-top: calc(16px * var(--space));
    background: var(--primary);
    color: var(--on-primary);
    border-radius: var(--radius-small);
    padding: 10px 22px;
    text-decoration: none;
    font-weight: 700;
}

/* ---- kind one: a title and a text ---- */

.home-popup--type-1.home-popup--layout-1 .home-popup__body {
    text-align: center;
}

.home-popup--type-1.home-popup--layout-2 .home-popup__body {
    text-align: start;
    border-inline-start: 4px solid var(--primary);
    padding-inline-start: calc(16px * var(--space));
}

/* ---- kind two: a text and a picture ---- */

.home-popup--type-2.home-popup--layout-1 .home-popup__image {
    margin-bottom: calc(16px * var(--space));
}

.home-popup--type-2.home-popup--layout-2 .home-popup__box {
    max-width: 720px;
}

.home-popup--type-2.home-popup--layout-2 .home-popup__image {
    float: inline-start;
    width: 42%;
    margin-inline-end: calc(16px * var(--space));
    margin-bottom: calc(8px * var(--space));
}

/* ---- kind three: a countdown ---- */

.home-popup__countdown {
    display: flex;
    gap: calc(12px * var(--space));
    justify-content: center;
    margin: 0 0 calc(16px * var(--space));
}

.home-popup__cell {
    margin: 0;
    text-align: center;
}

.home-popup__figure {
    display: block;
    font-size: 2.2em;
    font-weight: 700;
    color: var(--primary);
}

.home-popup__unit { color: var(--text-quiet); }

/* The first layout: three boxes. */
.home-popup--type-3.home-popup--layout-1 .home-popup__cell {
    min-width: 84px;
    padding: calc(12px * var(--space));
    background: var(--surface);
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius-small);
}

/* The second: one line, and the figure sits in it rather than over its name. */
.home-popup--type-3.home-popup--layout-2 .home-popup__countdown {
    gap: calc(8px * var(--space));
    align-items: baseline;
    flex-wrap: wrap;
}

.home-popup--type-3.home-popup--layout-2 .home-popup__cell {
    display: flex;
    align-items: baseline;
    gap: 4px;
}

.home-popup--type-3.home-popup--layout-2 .home-popup__figure {
    display: inline;
    font-size: 1.4em;
}

@media (max-width: 640px) {
    .home-popup__box { padding: calc(18px * var(--space)); }

    .home-popup--type-2.home-popup--layout-2 .home-popup__image {
        float: none;
        width: 100%;
        margin-inline-end: 0;
        margin-bottom: calc(12px * var(--space));
    }

    .home-popup--type-3.home-popup--layout-1 .home-popup__cell { min-width: 0; flex: 1; }
}

/* ---------- less motion, and print: the closing block of this file ----------

   The two closing blocks of the stylesheet, and they must stay the closing
   blocks. The slider's stop weighs exactly what the slider's turn weighs, and
   a tie between two rules of equal weight goes to whichever is written later —
   so the stop lives here, at the end, and a test pins it here. Anything added
   to the file after this point would silently take the tie and set the slider
   turning again under reduced motion, which is the defect T-010 found.

   Everything below that belongs to the projects is written into these same two
   blocks for that reason, rather than into two new ones after them. */
@media (prefers-reduced-motion: reduce) {
    .pcard {
        transition: none;
    }

    .pcard:hover {
        transform: none;
    }

    /* The slider stands still on its first slide. The dots keep working — a
       press jumps, and a jump is not motion. Repeated here, in the file's own
       closing block, so it keeps winning the tie. */
    .home-slider .home-slider__track {
        animation: none;
    }

    /* The impact map's pins stop beating and stay plainly where they are — the
       same answer as the slider's, and written here for the same reason: the
       beat weighs exactly what this stop weighs, so the stop has to be later in
       the file to take the tie. The globe that turns by itself is stopped by the
       drawing, since no stylesheet can stop a rotation a script performs; the
       turning by hand is deliberately left alone, so a visitor who asked for
       less motion still has the whole world to turn. */
    .impact-map__pin {
        animation: none;
        opacity: 1;
    }

    .impact-map__name {
        transition: none;
    }

    /* The window over the home page **arrives without an entrance**: no fade
       and no rise, it is simply there when its moment comes. Its seconds are
       kept, because waiting is not motion — and the animation is kept too,
       because the animation is the only thing that makes it appear at all
       without a script. Written here, in the file's closing block, so it takes
       the tie against the rule above it. */
    .home-popup {
        animation-name: home-popup-appear;
        animation-duration: 0s;
        animation-timing-function: step-end;
    }
}

@media print {
    /* A form is not printed: nothing on paper can be pressed. Neither is the
       overlay, nor the play button — a frame prints as a grey rectangle. */
    .don,
    .video-overlay,
    .video-poster__play,
    .project__share {
        display: none;
    }

    .project--shape-1,
    .project--shape-2 {
        grid-template-columns: minmax(0, 1fr);
    }

    .pcard__veil,
    .video-poster__veil {
        display: none;
    }

    /* Print shows the first slide alone: the track stands still at the start,
       the window is one slide wide, and the sisters and the dots are not
       printed. The dimming veils go too — a dimmed picture on paper is a grey
       smear. */
    .home-slider .home-slider__track {
        animation: none;
        transform: none;
        width: 100%;
    }

    .home-slider .home-slide {
        width: 100%;
    }

    .home-slider .home-slide:not(:first-of-type),
    .home-slider .home-slider__dots,
    .home-slide .home-slide__veil,
    .home-stats .home-stats__veil,
    .home-call .home-call__veil {
        display: none;
    }
}

/* ====================================================================== */
/* The ways to pay — P-C. Tiles for the methods the association's gateway
   account opens, drawn on the basket page. Every tile equal: same size,
   same weight, the gateway's own order — «كلها تظهر بالتساوي، بلا إبراز
   ولا وسيلة مفضّلة». The chosen one is framed by the browser's own
   :checked and nothing else — no script, like everything public here.
   Colours are the theme's variables; the logos alone keep their own
   trademark colours, which is why they are <img> and not inline SVG.    */
/* ====================================================================== */

.pay-methods {
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    margin: 0 0 calc(16px * var(--space));
    padding: calc(12px * var(--space));
}

.pay-methods__title {
    color: var(--headings);
    font-weight: 700;
    padding: 0 6px;
}

.pay-methods__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: calc(10px * var(--space));
    margin-top: calc(8px * var(--space));
}

.pay-methods__tile {
    cursor: pointer;
    display: block;
}

/* The radio itself is hidden from the eye and kept for the machine — the
   clip pattern the forms use, never an offset that would stretch an RTL
   page sideways. */
.pay-methods__radio {
    position: absolute;
    clip-path: inset(50%);
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.pay-methods__face {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 92px;
    height: 100%;
    padding: 10px;
    text-align: center;
    background: var(--surface);
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius-small);
    transition: border-color var(--transition), box-shadow var(--transition);
}

/* The frame: the chosen tile and no other signal. Two widths of the
   primary line, and a soft ring so the frame reads on dense screens. */
.pay-methods__radio:checked + .pay-methods__face {
    border: var(--border-width-strong) solid var(--primary);
    box-shadow: 0 0 0 1px var(--primary);
}

.pay-methods__radio:focus-visible + .pay-methods__face {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* The official mark, its own colours untouched: max-height bounds it and
   the width follows the file's own ratio. */
.pay-methods__logo {
    max-height: 28px;
    max-width: 100%;
}

.pay-methods__name {
    color: var(--text);
    font-weight: 700;
}

.pay-methods__notice {
    color: var(--text-quiet);
    font-size: 0.8em;
}

/* ---- donations closed: the two told places -------------------------- */

/* Where the buttons stood on a project page. */
.don__closed {
    margin: 0;
    padding: calc(10px * var(--space)) 0 0;
    color: var(--text);
    font-weight: 700;
    border-top: var(--border-width) solid var(--line);
}

/* The basket page, above the quiet buttons, where the paying button was. */
.cart__closed {
    margin: 0 0 calc(12px * var(--space));
    color: var(--text);
    font-weight: 700;
    text-align: center;
}

/* The bar on the home page — the second told place, above everything. */
.donations-closed-bar {
    margin: 0;
    padding: calc(12px * var(--space)) 16px;
    background: var(--surface);
    color: var(--headings);
    font-weight: 700;
    text-align: center;
    border-bottom: var(--border-width) solid var(--line);
}

/* ---- the payment result page (P-D) ---------------------------------- */

.pay-result {
    max-width: 560px;
    margin: 0 auto;
    padding: calc(24px * var(--space)) 16px;
    text-align: center;
}

.pay-result__heading {
    margin: 0 0 calc(16px * var(--space));
    color: var(--headings);
}

/* The state, big and unmissable — its word is the book's own. */
.pay-result__state {
    margin: 0 0 calc(10px * var(--space));
    font-size: 1.3em;
    font-weight: 700;
}

.pay-result__state--succeeded { color: var(--primary); }

.pay-result__state--failed,
.pay-result__state--pending { color: var(--text); }

.pay-result__hint {
    margin: 0 0 calc(14px * var(--space));
    color: var(--text-quiet);
}

.pay-result__message {
    margin-bottom: calc(14px * var(--space));
}

.pay-result__facts {
    display: grid;
    gap: 8px;
    margin: 0 0 calc(18px * var(--space));
    padding: calc(12px * var(--space)) 16px;
    background: var(--surface);
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius-small);
}

.pay-result__fact {
    display: flex;
    justify-content: space-between;
    gap: 12px;
}

.pay-result__fact dt { color: var(--text-quiet); }

.pay-result__fact dd {
    margin: 0;
    font-weight: 700;
}

.pay-result__ways {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 12px;
    margin: 0;
}

/* The approximate converted figure on a tile — always with its mark (س٩). */
.pay-methods__approx {
    color: var(--text);
    font-size: 0.85em;
    font-weight: 700;
}

/* ---------- the cookie banner (P-045 ب/1) ---------- */

/* A bar across the foot of the page, over the site rather than pushing it up.
   Every colour is the theme's own variable and the letters are inherited from
   the page, so the bar changes with the theme and with the font the owner has
   switched on — it is not tied to either by name. */
.cookie-banner {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 40;
    background: var(--surface);
    border-top: var(--border-width-strong) solid var(--line-strong);
    box-shadow: var(--shadow-pop);
}

.cookie-banner__inner {
    max-width: var(--reading-width);
    margin: 0 auto;
    padding: calc(12px * var(--space)) 16px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.cookie-banner__text {
    margin: 0;
    color: var(--text);
    flex: 1 1 16rem;
}

.cookie-banner__answers {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* `font: inherit` and not a family: a button does not inherit the page's
   letters on its own, and naming one here would freeze this bar on a font
   while the rest of the site moved off it. */
.cookie-banner__button {
    font: inherit;
    font-weight: 700;
    cursor: pointer;
    padding: calc(8px * var(--space)) 20px;
    border-radius: var(--radius-small);
    border: var(--border-width) solid transparent;
    transition: var(--transition);
}

.cookie-banner__button--accept {
    background: var(--primary);
    color: var(--on-primary);
}

.cookie-banner__button--reject {
    background: transparent;
    color: var(--text);
    border-color: var(--line-strong);
}

.cookie-banner__button:hover {
    transform: var(--hover-transform);
    box-shadow: var(--hover-shadow);
}

/* On a phone the two answers take the width, side by side and equal, so
   neither is the easier one to reach. */
@media (max-width: 560px) {
    .cookie-banner__inner {
        flex-direction: column;
        align-items: stretch;
        text-align: center;
    }

    /* The basis above is a WIDTH while the bar is a row and becomes a HEIGHT
       the moment it turns into a column — sixteen rems of empty green between
       the sentence and the buttons. Seen on the phone in T-053 and nowhere
       else: a gap is read by the eye and by nothing in the code. */
    .cookie-banner__text {
        flex: 0 0 auto;
    }

    .cookie-banner__answers {
        justify-content: stretch;
    }

    .cookie-banner__answers form {
        flex: 1 1 0;
    }

    .cookie-banner__button {
        width: 100%;
    }
}

/* The way back to the bar: a button dressed as the small quiet line it is. */
.site-footer__cookies {
    margin: 0;
    padding: 0 16px calc(10px * var(--space));
    text-align: center;
}

.site-footer__cookies-link {
    font: inherit;
    font-size: 0.85em;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    color: var(--text-quiet);
    text-decoration: underline;
}

.site-footer__cookies-link:hover {
    color: var(--text);
}

/* ==========================================================================
   The zakat calculator (P-049).

   **Added at the end of the file. ⛔ Not one rule above is touched, moved or
   reordered, and every selector below carries the `zk-` prefix** — the owner's
   two conditions on opening this file, 08/08/2026.

   It holds no colour, no radius and no spacing of its own: every one of them is
   a custom property, like the rest of this stylesheet. The calculator wears the
   site's theme rather than a look of its own.

   **And it carries the whole of the six shapes** (§2/1 and §2/2) — three for the
   types screen and three for the home block — because «شكلٌ يختاره المالك» is a
   thing the eye can see or it is not a shape at all.
   ========================================================================== */

/* ---------- the journey's chrome ---------- */

.zk-lead {
    max-width: var(--reading-width);
    margin: 0 0 calc(1.5rem * var(--space));
    color: var(--text-quiet);
}

/* The three steps of §3, drawn by the stylesheet alone: there is no script on
   this site to move anything, and the step that is current wears a class the
   server wrote. */
.zk-steps {
    display: flex;
    flex-wrap: wrap;
    gap: calc(0.5rem * var(--space));
    margin: 0 0 calc(1.5rem * var(--space));
    padding: 0;
    list-style: none;
    counter-reset: none;
}

.zk-steps__step {
    display: flex;
    flex: 1 1 8rem;
    align-items: center;
    gap: 0.5rem;
    padding: calc(0.55rem * var(--space)) calc(0.8rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text-quiet);
    font-size: 0.95rem;
}

.zk-steps__number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    flex: 0 0 auto;
    border: var(--border-width) solid var(--line-strong);
    border-radius: 50%;
    font-size: 0.85rem;
}

/* Behind him: done, and quiet about it. */
.zk-steps__step--done {
    border-color: var(--line-strong);
    color: var(--text);
}

.zk-steps__step--done .zk-steps__number {
    border-color: var(--primary);
    color: var(--primary);
}

/* Where he is standing — the one step the eye should land on. */
.zk-steps__step--current {
    border-color: var(--primary);
    color: var(--text);
    font-weight: 700;
}

.zk-steps__step--current .zk-steps__number {
    border-color: var(--primary);
    background: var(--primary);
    color: var(--on-primary);
}

/* The religious notice under every result, and under the types screen. Quiet
   deliberately: it is a caveat and not a heading. */
.zk-disclaimer {
    max-width: var(--reading-width);
    margin: calc(2rem * var(--space)) 0 0;
    padding-top: calc(1rem * var(--space));
    border-top: var(--border-width) solid var(--line);
    color: var(--text-quiet);
    font-size: 0.9rem;
}

/* §11's second state: the calculator exists and says why it is down. */
.zk-closed {
    max-width: var(--reading-width);
    padding: calc(1.25rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

/* The nisab under the types, worked out at the moment the page is drawn. */
.zk-nisab-line {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem;
    margin: calc(1.5rem * var(--space)) 0 0;
    color: var(--text-quiet);
    font-size: 0.95rem;
}

.zk-resume {
    margin: calc(1rem * var(--space)) 0 0;
}

/* ---------- the one control this section has ---------- */

/* Worn by a button and by a link alike — the basket's own reasoning: what a
   control looks like is about its weight on the page, not about whether it
   posts or goes. */
.zk-button {
    display: inline-block;
    padding: calc(0.55rem * var(--space)) calc(1.1rem * var(--space));
    border: var(--border-width) solid var(--line-strong);
    border-radius: var(--radius);
    background: transparent;
    color: var(--text);
    font: inherit;
    text-decoration: none;
    text-align: center;
    cursor: pointer;
    transition: box-shadow var(--transition), transform var(--transition);
}

.zk-button:hover {
    box-shadow: var(--hover-shadow);
    transform: var(--hover-transform);
}

.zk-button--strong {
    border-color: var(--primary);
    background: var(--primary);
    color: var(--on-primary);
    font-weight: 700;
}

.zk-button--quiet {
    border-color: var(--line);
    color: var(--text-quiet);
}

.zk-button--small {
    padding: 0.25rem 0.6rem;
    border-color: var(--line);
    color: var(--text-quiet);
    font-size: 0.85rem;
}

/* ---------- the types screen · shape 1 of 3 ---------- */

/* The list itself. All three shapes are the same list wearing a different
   class, so the markup never changes with the owner's choice. */
.zk-types {
    display: grid;
    gap: calc(1.25rem * var(--space));
    margin: 0;
    padding: 0;
    list-style: none;
}

.zk-type {
    display: flex;
}

/* ✅ **The whole card is the link** (§2/3) — a finger on a phone lands on the
   type wherever it falls, and the button inside is drawn by this stylesheet as
   part of the same link, never a second one. */
.zk-type__link {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 0.5rem;
    padding: calc(1.25rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
    color: var(--text);
    text-decoration: none;
    transition: box-shadow var(--transition), transform var(--transition);
}

.zk-type__link:hover {
    box-shadow: var(--hover-shadow);
    transform: var(--hover-transform);
}

.zk-type__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--primary);
}

.zk-type__icon svg {
    width: 1.75rem;
    height: 1.75rem;
}

.zk-type__name {
    color: var(--headings);
    font-size: 1.15rem;
    font-weight: 700;
}

.zk-type__line {
    color: var(--text-quiet);
    font-size: 0.95rem;
}

/* Drawn as a button, and it is not one: the card is the link. */
.zk-type__button {
    align-self: flex-start;
    margin-top: auto;
    padding: 0.35rem 0.9rem;
    border: var(--border-width) solid var(--primary);
    border-radius: var(--radius);
    color: var(--primary);
    font-size: 0.9rem;
}

/* **Shape 1 — cards with a round icon on the edge, overlapping it.**
   Three across on a desktop, two on a tablet, one on a phone (§2/1). The icon
   sits on the inline start, which is the right-hand edge in this direction, and
   hangs half outside the card. */
.zk-types--shape-1 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.zk-types--shape-1 .zk-type__link {
    position: relative;
    margin-inline-start: 1.6rem;
    padding-inline-start: calc(2.25rem * var(--space));
}

.zk-types--shape-1 .zk-type__icon {
    position: absolute;
    top: calc(1.1rem * var(--space));
    inset-inline-start: -1.6rem;
    width: 3.2rem;
    height: 3.2rem;
    border: var(--border-width) solid var(--line);
    border-radius: 50%;
    background: var(--page);
    box-shadow: var(--shadow);
}

/* **Shape 2 — large squares, the drawing above the middle and the name under
   it.** Four across on a desktop, two on a tablet and on a phone (§2/1). */
.zk-types--shape-2 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

.zk-types--shape-2 .zk-type__link {
    align-items: center;
    justify-content: center;
    min-height: 12rem;
    padding-block: calc(1.75rem * var(--space));
    text-align: center;
}

.zk-types--shape-2 .zk-type__icon svg {
    width: 2.75rem;
    height: 2.75rem;
}

.zk-types--shape-2 .zk-type__button {
    align-self: center;
}

/* **Shape 3 — a plain vertical list, one line per type with a small drawing.**
   One across at every width, which is the whole of it (§2/1). */
.zk-types--shape-3 {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
}

.zk-types--shape-3 .zk-type__link {
    flex-direction: row;
    align-items: center;
    gap: 0.75rem;
    padding: calc(0.9rem * var(--space)) calc(1rem * var(--space));
    border-radius: 0;
    box-shadow: none;
}

/* One line under the next: the row above keeps its own bottom edge, so the list
   reads as one block and not as a stack of separated cards. */
.zk-types--shape-3 .zk-type + .zk-type .zk-type__link {
    border-top: 0;
}

.zk-types--shape-3 .zk-type__icon svg {
    width: 1.35rem;
    height: 1.35rem;
}

.zk-types--shape-3 .zk-type__name {
    font-size: 1rem;
}

.zk-types--shape-3 .zk-type__line {
    flex: 1 1 auto;
}

.zk-types--shape-3 .zk-type__button {
    margin-top: 0;
    align-self: center;
}

/* ---------- the data screen ---------- */

.zk-form {
    display: grid;
    gap: calc(1.25rem * var(--space));
    max-width: var(--reading-width);
    margin: 0;
}

.zk-field {
    display: grid;
    gap: 0.4rem;
    margin: 0;
    padding: 0;
    border: 0;
}

.zk-field__label {
    color: var(--headings);
    font-weight: 700;
}

/* The minus in front of a box that takes away rather than adds. Isolated, so
   its direction cannot be pulled about by the Arabic beside it. */
.zk-field__minus {
    unicode-bidi: isolate;
    color: var(--text-quiet);
}

.zk-field__currency {
    color: var(--text-quiet);
    font-size: 0.9rem;
    font-weight: 400;
}

.zk-field__hint {
    margin: 0;
    color: var(--text-quiet);
    font-size: 0.9rem;
}

.zk-field input[type="text"],
.zk-field select {
    width: 100%;
    padding: calc(0.55rem * var(--space)) calc(0.7rem * var(--space));
    border: var(--border-width) solid var(--line-strong);
    border-radius: var(--radius);
    background: var(--page);
    color: var(--text);
    font: inherit;
}

.zk-field input[type="text"]:focus,
.zk-field select:focus {
    outline: var(--border-width-strong) solid var(--primary);
    outline-offset: 2px;
}

/* A yes or a no, a metal, a purpose — one row per answer, tall enough for a
   finger. */
.zk-choice {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0;
    cursor: pointer;
}

.zk-error {
    margin: 0;
    color: var(--error);
    font-size: 0.9rem;
}

/* A sentence that stands in place of a sum — «لا زكاة عليك» and its like. */
.zk-none {
    max-width: var(--reading-width);
    margin: 0;
    padding: calc(1rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

/* The pieces of jewellery: one bordered group per piece, numbered. */
.zk-pieces {
    display: grid;
    gap: calc(1rem * var(--space));
}

.zk-piece {
    display: grid;
    gap: calc(0.9rem * var(--space));
    margin: 0;
    padding: calc(1rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.zk-piece__legend {
    padding-inline: 0.5rem;
    color: var(--text-quiet);
    font-size: 0.9rem;
}

.zk-actions {
    display: flex;
    flex-wrap: wrap;
    gap: calc(0.75rem * var(--space));
    align-items: center;
}

/* ---------- the review screen ---------- */

.zk-review {
    max-width: var(--reading-width);
    margin: 0 0 calc(1.5rem * var(--space));
    padding: calc(1.1rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.zk-review__title {
    margin: 0 0 calc(0.75rem * var(--space));
    color: var(--headings);
    font-size: 1.1rem;
}

.zk-table {
    width: 100%;
    margin: 0 0 calc(0.9rem * var(--space));
    border-collapse: collapse;
}

.zk-table th,
.zk-table td {
    padding: calc(0.5rem * var(--space)) 0;
    border-bottom: var(--border-width) solid var(--line);
    text-align: start;
    font-weight: 400;
    vertical-align: top;
}

.zk-table td {
    text-align: end;
    white-space: nowrap;
}

.zk-table__sum th,
.zk-table__sum td {
    border-bottom: 0;
    border-top: var(--border-width-strong) solid var(--line-strong);
    font-weight: 700;
}

.zk-table__caption {
    padding-bottom: calc(0.5rem * var(--space));
    color: var(--headings);
    font-weight: 700;
    text-align: start;
}

/* The working, laid open on the result — wider than the review's tables because
   it carries the little «أخرجه من الحسبة» press in a third column. */
.zk-table--working {
    max-width: var(--reading-width);
}

.zk-table--working td:last-child {
    width: 1%;
    text-align: end;
}

/* The pure weight, said beside the piece it belongs to and never on the entry
   screen (§4/2). */
.zk-review__pure {
    display: block;
    color: var(--text-quiet);
    font-size: 0.85rem;
    white-space: nowrap;
}

.zk-review__hawl {
    max-width: var(--reading-width);
    margin: 0 0 calc(1.25rem * var(--space));
    color: var(--text-quiet);
}

/* A small word riding beside a row — the standard of the nisab, or a piece that
   is exempt because it is in use. */
.zk-tag {
    display: inline-block;
    padding: 0.05rem 0.45rem;
    border: var(--border-width) solid var(--line);
    border-radius: 999px;
    color: var(--text-quiet);
    font-size: 0.8rem;
    white-space: nowrap;
}

/* ---------- the result screen ---------- */

/* The figure itself — the one thing on this page a visitor came for. */
.zk-result {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem;
    max-width: var(--reading-width);
    margin: 0 0 calc(1rem * var(--space));
    padding: calc(1.25rem * var(--space));
    border: var(--border-width-strong) solid var(--primary);
    border-radius: var(--radius);
    background: var(--surface);
}

.zk-result__label {
    color: var(--text-quiet);
}

.zk-result__amount {
    color: var(--headings);
    font-size: 2rem;
    font-weight: 700;
}

.zk-result__currency {
    color: var(--text-quiet);
}

/* ⛔ Information and nothing else: no card, no conversion (§6/2). */
.zk-impact,
.zk-source {
    max-width: var(--reading-width);
    margin: 0 0 calc(1rem * var(--space));
    color: var(--text-quiet);
    font-size: 0.9rem;
}

.zk-source__manual {
    display: block;
}

.zk-join {
    max-width: var(--reading-width);
    margin: calc(1.5rem * var(--space)) 0;
}

.zk-join__title {
    margin: 0 0 calc(0.75rem * var(--space));
    color: var(--headings);
    font-size: 1.05rem;
}

.zk-join__list {
    display: flex;
    flex-wrap: wrap;
    gap: calc(0.6rem * var(--space));
    margin: 0;
    padding: 0;
    list-style: none;
}

.zk-actions--result {
    margin-top: calc(1.5rem * var(--space));
}

/* ---------- the home block · three shapes ---------- */

/* What is in it is fixed by §1 — a title, a line, the nisab bar and one button,
   ⛔ and no cards of the types. The three shapes below differ in how those four
   things are laid out and in nothing else. */
.zk-block__body {
    display: grid;
    gap: calc(0.6rem * var(--space));
    justify-items: start;
}

.zk-block__title {
    margin: 0;
    color: var(--headings);
    font-size: 1.5rem;
}

.zk-block__sentence {
    margin: 0;
    color: var(--text-quiet);
}

/* The nisab bar. Worked out as the page is drawn and ⛔ never stored. */
.zk-block__nisab {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem;
    margin: 0;
    padding: calc(0.5rem * var(--space)) calc(0.9rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: 999px;
    background: var(--page);
    font-size: 0.95rem;
}

.zk-block__nisab-label {
    color: var(--text-quiet);
}

/* **Shape 1 — a bar across the page.** Everything on one line while there is
   room for it, and the button pushed to the far end. */
.zk-block--1 .zk-block__body {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: calc(0.9rem * var(--space));
    padding: calc(1.25rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.zk-block--1 .zk-block__title {
    font-size: 1.25rem;
}

.zk-block--1 .zk-block__sentence {
    flex: 1 1 14rem;
}

/* **Shape 2 — a card in the middle.** */
.zk-block--2 .zk-block__body {
    justify-items: center;
    max-width: var(--reading-width);
    margin-inline: auto;
    padding: calc(2rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
    text-align: center;
}

/* **Shape 3 — a block with a picture beside it.** With no picture chosen the
   writing simply takes the whole width: a block that broke without one would be
   a block that needs the media library to draw. */
.zk-block--3 {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: calc(1.5rem * var(--space));
    align-items: center;
    padding: calc(1.5rem * var(--space));
    border: var(--border-width) solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
}

.zk-block__image {
    width: 100%;
    height: 100%;
    max-height: 18rem;
    border-radius: var(--radius);
    object-fit: cover;
}

/* ---------- narrower than a desktop ---------- */

/* The tablet step of §2/1: shape 1 drops from three across to two, and shape 2
   from four to two. Shape 3 is one at every width and needs no step. */
@media (max-width: 64rem) {
    .zk-types--shape-1 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .zk-types--shape-2 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* The phone step. Shape 1 goes to one across; **shape 2 stays at two**, which
   is the owner's own table — four then two then two. */
@media (max-width: 48rem) {
    .zk-types--shape-1 {
        grid-template-columns: minmax(0, 1fr);
    }

    .zk-types--shape-2 .zk-type__link {
        min-height: 9rem;
        padding-block: calc(1.1rem * var(--space));
    }

    .zk-types--shape-2 .zk-type__icon svg {
        width: 2rem;
        height: 2rem;
    }

    /* One line per type is still one line per type on a phone, but the sentence
       under the name would push the row taller than the finger needs. */
    .zk-types--shape-3 .zk-type__link {
        flex-wrap: wrap;
    }

    .zk-steps__step {
        flex: 1 1 100%;
    }

    /* The picture goes above the writing rather than beside it: a column half a
       phone wide is not a picture and not a paragraph. */
    .zk-block--3 {
        grid-template-columns: minmax(0, 1fr);
    }

    .zk-block__image {
        max-height: 12rem;
    }

    /* A row of controls becomes a column, each across the width, so no press is
       a sliver. */
    .zk-actions {
        flex-direction: column;
        align-items: stretch;
    }

    .zk-actions form {
        display: contents;
    }

    .zk-table td {
        white-space: normal;
    }
}

/* ---- the empty state (ب-١, 10/08/2026) --------------------------------- *
 *
 * A public page whose content has not been entered yet. It is drawn whole —
 * heading, header, footer — and says so in a sentence, because a visitor reads
 * a blank as a fault and a missing page as a broken link (INSPECTION م-٣).
 *
 * The same three parts as the panel's, in this file's own variables. There is
 * no button: a visitor has no first action to take here. */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    padding: 3rem 1rem;
    text-align: center;
}

.empty-state__icon {
    display: block;
    width: 3.25rem;
    height: 3.25rem;
    color: var(--text-quiet);
    opacity: 0.45;
}

.empty-state__icon svg {
    display: block;
    width: 100%;
    height: 100%;
}

.empty-state__sentence {
    margin: 0;
    color: var(--text-quiet);
    line-height: 1.8;
}
