/* AMIRI QURAN, for literal revelation only. A different font from plain Amiri,
   which sits below and stays on the hadith. This one carries the full set of
   Quranic marks that Uthmani text needs. Subset pulled from Google Fonts and
   self hosted like every other face here, so the page still makes zero
   third party requests. */
@font-face{
  font-family:'Amiri Quran';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url(fonts/AmiriQuran-400-arabic.woff2?f=2) format('woff2');
  unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0897-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC;
}
/* SELF-HOSTED FONTS, generated 8 Aug 2026 from the CDNs' own css so nothing
 is hand-typed. Licences checked and logged: Sentient is Fontshare's free
 licence which allows self-hosting, the rest are OFL. Regenerate via the
 commands in the git log if a font is ever updated. */
/* Amiri 400 arabic */
@font-face {
  font-family: 'Amiri';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/Amiri-400-arabic.woff2?f=2) format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC4, U+10EFC-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
}
/* Amiri 400 latin */
@font-face {
  font-family: 'Amiri';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/Amiri-400-latin.woff2?f=2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Reem Kufi 500 arabic */
@font-face {
  font-family: 'Reem Kufi';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ReemKufi-500-arabic.woff2?f=2) format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC4, U+10EFC-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
}
/* Source Serif 4, VARIABLE file, one file serves weights 400 to 600.
   Google shipped the identical file for both weights, verified by hash. */
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(fonts/SourceSerif4-400-latin.woff2?f=2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(fonts/SourceSerif4-400-latin-ext.woff2?f=2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Sentient 400 */
@font-face {
  font-family: 'Sentient';
  src: url(fonts/Sentient-400.woff2?f=2) format('woff2');
  font-weight: 400;
  font-display: swap;
  font-style: normal;
}
/* Sentient 500 */
@font-face {
  font-family: 'Sentient';
  src: url(fonts/Sentient-500.woff2?f=2) format('woff2');
  font-weight: 500;
  font-display: swap;
  font-style: normal;
}
/* Sentient 700 */
@font-face {
  font-family: 'Sentient';
  src: url(fonts/Sentient-700.woff2?f=2) format('woff2');
  font-weight: 700;
  font-display: swap;
  font-style: normal;
}

/* Ummul Qura Quranic School
   Palette rides on variables. Branding lock swaps ONLY this block. */
/* LOCKED 5 Aug 2026, the Mushaf palette, tone C.
   The paper was deliberately DEEPENED from #FAF7F0 after Hamza said three times
   that the page hurt his eyes. He was right: the old cream was 2% off pure white,
   which is a lamp at night. This tone reflects 11% less light and is what a real
   printed mushaf page actually looks like. Every colour below was re-verified
   against it, all text passes WCAG AA. Do not lighten it back. */
:root{
  --paper:#F1EAD9;      /* page background, real mushaf paper */
  --surface:#E9E0CB;    /* cards, strips */
  --ink:#1B2B25;        /* deep green-black, text, marks, filled buttons. 12.34:1 on paper */
  --muted:#575F55;      /* secondary text. 5.52:1, AA pass */
  --line:#D6CBB1;       /* hairlines */
  --accent:#3A5749;     /* quiet green, links only. 6.63:1, AA pass as text */
  --rubric:#82372A;     /* madder red, kickers and one highlight. 6.92:1 */
  --accent-ink:#F1EAD9; /* text on ink buttons */

  --serif:'Sentient', Georgia, serif;
  --body:'Source Serif 4', Georgia, serif;
  /* AMIRI, chosen 6 Aug 2026 by Hamza looking at it, which beats how it got here
     before. Markazi Text was picked by two agents on measured technical grounds
     and it IS technically correct, but it is a face built for small running text
     and at 46px on a dark band it reads plain and thin. Amiri is classical Naskh,
     the style serious Arabic printing has used for a century.
     This is plain Amiri, NOT Amiri Quran. Amiri Quran is a mushaf face and our
     text is a hadith, not revelation. That distinction is deliberate, see the log.
     Real Arabic fallbacks matter more than Latin ones: generic serif means Times
     New Roman on Windows, which mangles harakat on the one line that must never
     look wrong. */
  --arabic:'Amiri', 'Traditional Arabic', 'Segoe UI', 'Geeza Pro', serif;
  /* Reem Kufi is the LOGO face only, never body text. Geometric Kufi is a display
     script: it is built for a name on a wall, not for sentences. The approved
     Option 4 nameplate is set in it. */
  --kufi:'Reem Kufi', 'Segoe UI', sans-serif;

  --shell:1080px;
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
}

/* ---------- MOTION ----------
   Rules carried over from the MotionOx build brain, adapted DOWN for a Quran
   school. This is a calm settle, not cinema. Hard rules, do not break them:

   1. VISIBLE BY DEFAULT. The reveal only arms itself if JS runs. A failed
      trigger can therefore never blank the page. This is the single most
      important rule and it cost MotionOx real time to learn.
   2. transform and opacity ONLY, so it stays on the GPU and never jitters.
   3. ONE unified beat per section, never a slow one-by-one cascade.
   4. A perceptible glide, not a pop. 0.7s with an eased-out curve.
   5. prefers-reduced-motion kills all of it, handled above.
   6. Nothing moves in the sacred band. The hadith does not perform. */
.js-motion [data-rise]{
  opacity:0;
  transform:translateY(14px);
  transition:opacity .7s cubic-bezier(.16,1,.3,1), transform .7s cubic-bezier(.16,1,.3,1);
  will-change:opacity, transform;
}
.js-motion [data-rise].is-in{
  opacity:1;
  transform:none;
}
/* The second element in a pair follows a beat later. One step, never a queue. */
.js-motion [data-rise="2"]{transition-delay:.09s}
.js-motion [data-rise="3"]{transition-delay:.18s}

body{
  background:var(--paper);
  color:var(--ink);
  font-family:var(--body);
  font-size:17px;
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
}

.shell{max-width:var(--shell);margin:0 auto;padding:0 24px}
.section{padding:88px 0}

.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.skip{position:absolute;left:-999px;top:0;background:var(--ink);color:var(--paper);padding:10px 16px;z-index:99}
.skip:focus{left:0}

/* Must stay ABOVE the header height or an anchor link lands with the heading
   hidden behind the sticky bar. Header is 86px, so 98. */
section[id]{scroll-margin-top:98px}
strong{font-weight:600}
/* Sentient loads 400/500/700 only, so a <strong> inside a heading would silently
   request 600 and get a synthesised smear. Headings keep their own weight. */
h1 strong,h2 strong,h3 strong,.qa summary strong,.foot-name strong{font-weight:inherit}

/* Keyboard focus must be visible on the ink buttons, where the browser's default
   dark ring would sit on a dark background and disappear. */
:focus-visible{outline:2px solid var(--rubric);outline-offset:3px}
.btn:focus-visible,.nav-cta:focus-visible{outline-color:var(--paper);outline-offset:-5px}

h1,h2,h3{font-family:var(--serif);font-weight:500;line-height:1.15;text-wrap:balance}
h1{font-size:clamp(34px,5vw,52px);font-weight:700}
h2{font-size:clamp(26px,3.6vw,36px);margin-bottom:20px}
h3{font-size:21px;margin-bottom:8px}

/* The salam above the hero kicker: Amiri, ink, quiet. A greeting in the
   reader's own deen does more homely warmth than any texture could. */
.hero-salam{font-family:var(--arabic);font-size:26px;line-height:1.6;margin-bottom:6px;color:var(--accent)}
.kicker{
  font-family:var(--body);
  font-size:12.5px;
  letter-spacing:.18em;
  text-transform:uppercase;
  /* RUBRIC, not accent. This is the rubrication a manuscript uses: one warm red
     for the small headers, ink for everything else. It was declared in the
     palette and used nowhere, which is why the page read as a single flat hue. */
  color:var(--rubric);
  margin-bottom:14px;
  font-weight:600;
}

p{max-width:62ch}
a{color:var(--accent)}
/* ---------- LIFE ----------
   The page answered no input at all: every hover was a hard 0ms snap, which is
   the loudest plain-HTML tell there is. State changes now arrive instead of
   flipping. Movement stays 1 to 3px, this is a book, not an app. */
.btn,.nav-cta,.nav-list a,.gal-btn,.qa summary,a{
  transition:background-color .22s ease,color .22s ease,border-color .22s ease,
             transform .12s ease,box-shadow .3s ease;
}
.btn:active,.nav-cta:active,.gal-btn:active{transform:translateY(1px)}
a:not(.btn):not(.nav-cta):not(.brand){
  text-decoration:underline;text-decoration-color:transparent;
  text-decoration-thickness:1px;text-underline-offset:3px;
  transition:text-decoration-color .22s ease,color .22s ease;
}
a:not(.btn):not(.nav-cta):not(.brand):hover{text-decoration-color:currentColor}

.pending{
  background:#FFF3C9;
  outline:1px dashed #C9A227;
  padding:0 4px;
  font-size:.9em;
}
/* Anything still waiting on the client must LOOK unfinished. A dead button that
   looks finished is the one thing nobody catches before launch. Delete this rule
   and every data-pending attribute on ship day. */
[data-pending]{outline:2px dashed #C9A227;outline-offset:3px;position:relative;margin-bottom:24px}
[data-pending]::after{
  content:"link pending";
  position:absolute;left:50%;top:calc(100% + 7px);transform:translateX(-50%);
  background:#FFF3C9;color:#7A5C10;font-family:var(--body);
  font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  padding:2px 8px;border-radius:2px;white-space:nowrap;
}

/* ---------- header ---------- */
.site-head{
  position:sticky;top:0;z-index:50;
  background:var(--paper);
  background:color-mix(in srgb, var(--paper) 92%, transparent);
  -webkit-backdrop-filter:blur(8px);
  backdrop-filter:blur(8px);
  border-bottom:1px solid var(--line);
  transition:box-shadow .3s ease,border-color .3s ease;
}
/* When the page moves beneath it, the bar casts a shadow on it. That single
   cue is what separates a floating bar from a pasted rectangle. */
.site-head.is-stuck{
  box-shadow:0 10px 22px -20px rgba(27,43,37,.85);
  border-bottom-color:color-mix(in srgb, var(--ink) 22%, var(--line));
}
/* 86px, not 72. The nameplate is three lines now (English, sub, Arabic) and at
   72px it measured 69px tall, so it had 3px of air and read cramped. If the
   Arabic line is ever removed, put this back to 72. */
.head-row{display:flex;align-items:center;justify-content:space-between;height:86px}
/* ---------- THE NAMEPLATE, Option 4, chosen by the family 7 Aug 2026 ----------
   This option is a NAMEPLATE, so it has no icon. That is the design, not an
   omission, and .brand-mark is deliberately gone from the header and footer.
   English leads and the Arabic sits under it, which is Muhammad's own
   instruction and a flip of the card he was first sent. */
.brand{display:flex;align-items:center;gap:12px;text-decoration:none;color:var(--ink)}
/* The knockout hole lives in CSS, not in a fill="var(...)" presentation attribute.
   If a presentation attribute ever fails to parse, fill falls back to BLACK, which
   would put a black dot in the middle of the logo and nobody would see it in Chrome. */
.brand-name{display:block;font-family:var(--serif);font-weight:500;font-size:20px;line-height:1}
.brand-sub{display:block;font-size:10px;letter-spacing:.28em;text-transform:uppercase;color:var(--muted);margin-top:3px}
/* The Arabic under the English. A hairline rule separates them so the two
   scripts read as one lockup rather than two stacked labels. Reem Kufi sits
   optically small for its point size, hence 17px against the 20px English. */
.brand-ar{
  display:block;font-family:var(--kufi);font-weight:500;font-size:18px;
  /* The dividing rule is GONE and the gap is tight. Hamza said too much gap and
     he was right: a rule plus 14px of padding split one lockup into two labels.
     Kufi is kept on purpose. It is the square architectural script, the one used
     to carve a NAME into a building or a seal. Amiri, the hadith face, is Naskh,
     made for reading sentences. A logo and body text using different Arabic
     scripts is correct practice, exactly like Sentient for the logo and Source
     Serif for the paragraphs in English. */
  line-height:1.15;color:var(--ink);margin-top:4px;
  /* direction:rtl is REQUIRED for correct Arabic shaping and joining.
     text-align:left is then required to undo what rtl does to the BLOCK, which is
     shove it to the right edge. Without this the Arabic floats away from the
     English above it and the lockup reads as two unrelated labels. */
  direction:rtl;
  text-align:left;
}

.nav-list{display:flex;gap:28px;list-style:none;align-items:center}
.nav-list a{text-decoration:none;color:var(--ink);font-size:15.5px}
.nav-list a:hover{color:var(--accent)}
.nav-cta{
  background:var(--ink);color:var(--accent-ink)!important;
  padding:9px 18px;border-radius:3px;font-weight:600;
}
.nav-cta:hover{background:var(--accent)}
.nav-toggle{display:none}

/* ---------- hero ---------- */
.hero{padding:96px 0 72px;border-bottom:1px solid var(--line);overflow:hidden}
.hero .shell{max-width:1280px}
/* Equal columns. Hamza flagged the photo small three times, and on a wide
   monitor the old text-heavy split left a void of dark to the photo's right.
   The photo carries as much meaning as the words, it gets as much room. */
.hero-grid{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center}
.lede{font-size:19px;color:var(--muted);margin-top:18px}
.hero-actions{margin-top:32px}
.btn{
  display:inline-block;text-decoration:none;border-radius:3px;
  padding:14px 28px;font-weight:600;font-size:16.5px;
}
.btn-primary{background:var(--ink);color:var(--accent-ink)}
.btn-primary:hover{background:var(--accent)}
.btn-note{font-size:13.5px;color:var(--muted);margin-top:10px}
.hero-art{position:relative}
/* The photo sits in a frame with the shamsa BEHIND it, bleeding out past the
   corners. The pattern frames the photograph the way an illuminated border
   frames a page, instead of the two competing for the same slot. */
.hero-photo-wrap{position:relative;display:flex;align-items:center;justify-content:center}
.hero-photo{
  position:relative;z-index:1;
  /* No pixel cap. The photo fills its grid column, and the hero's own shell is
   wider than the page's 1080 so the opening feels generous on a big monitor.
   Hamza asked twice why it sat small, the answer was the page frame, not the
   image. The 1600px export keeps it sharp at any size this can reach. */
  width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;
  border:1px solid var(--line);border-radius:6px;
  /* two layers: a tight contact shadow plus a soft ambient one. The old single
     40px-blur-minus-22px-spread shadow computed to nearly nothing on screen. */
  box-shadow:0 14px 34px -18px rgba(27,43,37,.42), 0 2px 6px -3px rgba(27,43,37,.18);
}
/* The shamsa is layered, so the eye finds the centre first and the outer ring
   stays a whisper. One flat opacity would make it a grey blob. */
/* ---------- trust ---------- */
/* No border-top: the hero already draws that edge, two would stack into a 2px
   line while every other divider on the page is 1px, and it would read as a bug. */
.trust{background:var(--surface);border-bottom:1px solid var(--line)}
.trust-row{
  display:grid;grid-template-columns:repeat(4,1fr);
  gap:18px;padding-top:26px;padding-bottom:26px;text-align:center;
}
.trust-item strong{display:block;font-family:var(--serif);font-size:19px;font-weight:500}
.trust-item span{font-size:13px;color:var(--muted);letter-spacing:.04em}

/* ---------- gallery ----------
   Removed 6 Aug 2026, restored the same day with a rule about WHAT may go in it.
   The photo rules live in index.html at the section itself. Read them before
   putting any image in here. */
.gallery{padding:56px 0 8px}
.gallery-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:18px}
.gallery-head .kicker{margin-bottom:0}
.gal-btn{
  position:absolute;top:50%;transform:translateY(-50%);z-index:2;
  width:44px;height:44px;border-radius:50%;border:1px solid var(--line);
  background:var(--paper);color:var(--ink);font-size:18px;cursor:pointer;
  box-shadow:0 6px 16px -10px rgba(27,43,37,.5);
}
.gal-prev{left:12px}
.gal-next{right:12px}
.gal-btn:hover{background:var(--surface)}
.gal-btn[disabled]{opacity:0;pointer-events:none}
.gal-btn[disabled]:hover{background:var(--paper)}
/* THE FADE GOES ON THE TRACK, NOT ON THIS WRAPPER, and that is the whole point.
   The two arrow buttons are children of .gallery-mask, so a mask here ate the
   CONTROLS along with the cards: measured at 1440 the next button spanned
   1180 to 1224 while the fade ran 1176 to 1236, so its right half dropped to
   about 20% opacity and lost its border and shadow. At 500 the entire button
   sat inside the fade and covered the exact sliver of the next card that the
   fade exists to advertise. A mask applies to a whole subtree, so anything that
   must stay crisp has to live outside the masked element. */
.gallery-mask{position:relative}
.gallery-track{
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 60px),transparent 100%);
          mask-image:linear-gradient(to right,#000 calc(100% - 60px),transparent 100%);
}
.gallery-mask[data-end] .gallery-track{-webkit-mask-image:none;mask-image:none}
.gallery-track{
  display:flex;gap:16px;overflow-x:auto;
  scroll-snap-type:x mandatory;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
  padding-bottom:8px;
}
.gallery-track::-webkit-scrollbar{display:none}
/* 460px cards, not 340. At 340 the whole strip nearly fitted a desktop screen,
   only 48px of scroll existed, and the controls read as dead buttons. At 460 the
   strip genuinely travels: with the three cards it now holds, maxScroll measures
   380px at 1440 and about 2.17 cards are visible.
   The old version of this comment said four photos, dots 2 and 3, and two and a
   half cards. The dots were removed, the count went five to four to three, and
   the comment tracked none of it. Numbers written into a comment go stale the
   moment the thing changes, so re-measure before trusting any of these. */
.shot{flex:0 0 min(460px,80vw);scroll-snap-align:start}
.shot,.course,.about-photo{transition:transform .5s cubic-bezier(.16,1,.3,1),box-shadow .5s cubic-bezier(.16,1,.3,1)}
.shot:hover,.about-photo:hover{transform:translateY(-3px);box-shadow:0 16px 30px -20px rgba(27,43,37,.45)}
.course:hover{transform:translateY(-2px);box-shadow:0 12px 24px -18px rgba(27,43,37,.35)}
/* All cards EQUAL width on purpose. A wider lead card made the arrows land
   mid-photo, a click revealed half a shoulder, Hamza laughed at it and he was
   right. Equal cards means every arrow click lands on a whole photo. */
/* height:auto is LOAD-BEARING on every img with width/height attributes.
   The attribute height maps to a real 750px height, a fixed height beats
   aspect-ratio, and without this line every card rendered as a 340x750
   portrait: sideways crops, arrows landing on shoulders, and the old 680px
   files stretched 47% which was the exact blur Hamza kept reporting. */
.shot img{-webkit-user-drag:none;user-select:none;width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;border-radius:6px;border:1px solid var(--line)}
/* the strip must FEEL like a slider: grab cursor, edge arrows on the image */
.gallery-track{cursor:grab}
.gallery-track.dragging{cursor:grabbing;scroll-snap-type:none;user-select:none}
/* ---------- the teachers ---------- */
.teacher-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:36px}
.teacher{border:1px solid var(--line);border-radius:6px;padding:22px;background:color-mix(in srgb, var(--surface) 55%, var(--paper))}
.teacher-photo{aspect-ratio:1;border-radius:6px;background:var(--surface);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;margin-bottom:16px;overflow:hidden}
.teacher-photo img{width:100%;height:100%;object-fit:cover}
.teacher-role{font-size:12.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rubric);font-weight:600;margin:2px 0 10px}
.teacher p{font-size:15px}
.teacher-note{margin-top:26px;color:var(--muted);font-size:15px}
@media (max-width:900px){.teacher-grid{grid-template-columns:1fr}}

/* ---------- the certificate section ---------- */
.cert-shell{display:grid;grid-template-columns:1fr 1.1fr;gap:56px;align-items:center}
.cert-hint{font-size:14px;color:var(--muted)}
.cert-open{
  border:none;padding:0;background:none;cursor:zoom-in;border-radius:6px;
  transition:transform .5s cubic-bezier(.16,1,.3,1),box-shadow .5s cubic-bezier(.16,1,.3,1);
}
.cert-open img{width:100%;height:auto;display:block;border-radius:6px;border:1px solid var(--line)}
.cert-open:hover{transform:translateY(-3px);box-shadow:0 16px 30px -20px rgba(27,43,37,.45)}
.cert-dialog{
  border:none;padding:0;background:none;max-width:min(92vw,1100px);
}
.cert-dialog::backdrop{background:rgba(27,43,37,.72)}
.cert-dialog img{width:100%;max-height:88vh;object-fit:contain;display:block;border-radius:6px}
.cert-close{
  position:absolute;top:10px;right:10px;width:40px;height:40px;border-radius:50%;
  border:none;cursor:pointer;background:var(--paper);color:var(--ink);font-size:17px;
}
@media (max-width:900px){
  .cert-shell{grid-template-columns:1fr;gap:26px}
}

/* ---------- about ---------- */
.about-grid{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center}
.about p{margin-bottom:14px}
.about-img{width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;border:1px solid var(--line);border-radius:6px;display:block}

/* ---------- THE SIGNATURE MOTIF ----------
   The khatim repeated large and faint, bleeding off a section edge. This is the
   MotionOx viewfinder trick carried across: one motif, used quietly, several
   times, is what makes a page feel composed instead of assembled.
   Rules: decorative only, never near the sacred band, never over text, and it
   must never create horizontal scroll. */
/* Was opacity .055, which is invisible. All the Islamic geometry in this build
   never reached the eye. Rubric rather than ink so the margins carry a warm
   blush like a printed mushaf instead of a grey smudge. */
.motif{
  position:absolute;
  pointer-events:none;
  color:var(--rubric);
  opacity:.11;
  width:min(460px,52vw);
  height:auto;
  aspect-ratio:1;
}
.has-motif{position:relative;overflow:hidden}
.motif-right{right:-13%;top:50%;transform:translateY(-50%)}
.motif-left{left:-15%;bottom:-22%}
@media (max-width:820px){
  .motif{width:min(320px,68vw);opacity:.09}
  .motif-right{right:-28%}
  .motif-left{left:-32%}
}

/* ---------- courses ----------
   The cream-on-cream tonal step measures only 1.09:1, which vanishes on a cheap
   phone under auto-brightness or a blue-light filter. So the band NEVER carries
   the page rhythm alone: hairline rules and the 88px section padding do the work,
   and the tone is a bonus for anyone whose screen shows it. */
.courses{background:var(--surface);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
/* FOUR columns, not three. There are 8 courses, and 8 into 3 leaves a ragged
   bottom row with one card alone beside an empty gap. 8 into 4 is two clean
   rows. If a course is ever added or removed, re-check this: the column count
   has to divide the card count or the grid looks broken at the bottom. */
.course-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-top:36px;
}
.course{
  background:var(--paper);border:1px solid var(--line);border-radius:6px;
  padding:26px 24px;
}
.course p{font-size:15.5px;color:var(--muted)}
.course-note{margin-top:26px;color:var(--muted);font-style:italic;font-family:var(--serif);font-weight:500}

/* ---------- how ---------- */
.how{border-bottom:1px solid var(--line)}
.steps{list-style:none;counter-reset:step;margin-top:36px;display:grid;gap:0}
.steps li{
  counter-increment:step;
  padding:22px 0 22px 64px;position:relative;
  border-bottom:1px solid var(--line);
  max-width:640px;
}
.steps li::before{
  content:counter(step);
  position:absolute;left:0;top:18px;
  width:40px;height:40px;border:1px solid var(--rubric);border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--serif);font-size:19px;font-weight:500;
}

/* ---------- why ----------
   Deliberately paper, not surface: the dark verse band below needs cream on
   BOTH sides. Cream meeting darker-cream meeting ink reads as an accident. */
.why{background:var(--surface);border-top:1px solid var(--line)}
.why-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:36px 48px;margin-top:36px}
.why-item p{font-size:15.5px;color:var(--muted)}

/* ---------- verse anchor, the one dark moment on the page ----------
   Judged by three independent lenses. Rules that make it read as an
   illuminated plate instead of a mistake, do NOT break these:
   full bleed, deeper padding than any other section, cream on BOTH sides,
   nothing sold inside it (no button, no price, no form), no animation,
   the source always visible, and it is the ONLY dark band on the site. */
.verse{
  text-align:center;
  padding:104px 24px;
  background:var(--ink);
;border-top:1px solid color-mix(in srgb, var(--paper) 25%, transparent);border-bottom:1px solid color-mix(in srgb, var(--paper) 25%, transparent)}
/* AMIRI, classical Naskh, replaced Markazi Text on 6 Aug 2026 when Hamza looked
   at the live band and said the Arabic read plain. Amiri carries full standard
   harakat and has the stroke contrast that survives being set large on a dark
   background. Keep lang="ar" on the element, it is what makes the browser apply
   Arabic shaping and punctuation rules rather than guessing from the characters. */
.verse-ar{
  font-family:var(--arabic);
  /* 400, not 500. AMIRI ONLY SHIPS 400 AND 700. Asking for 500 does not give a
     medium, the browser silently snaps to 400, so the old 500 was a lie that
     looked like a decision. If it ever needs more weight on the dark band, use
     700, do not invent a number in between. */
  font-weight:400;
  /* Was clamp(32px,4.6vw,46px). Hamza saw the Arabic look weaker on the real site
     than in the specimen and guessed spacing. He was right about the cause: the
     specimen was a FIXED 46px, while the site shrank the line on any window under
     1000px. At an 800px window the old rule gave 36.8px, a fifth smaller than the
     specimen he approved. Floor raised and the slope steepened so the hadith stays
     generous on a laptop and a phone, which is where most families will see it. */
  font-size:clamp(36px,5.6vw,50px);
  /* 1.9 put 50px letters inside a 95px box, so roughly 22px of invisible padding
     sat above AND below the Arabic and made every gap around it look wrong.
     Hamza spotted it as "a gap too much". 1.5 still clears Amiri's harakat with
     room to spare, and it must NOT go below about 1.4: on a narrow phone this
     line wraps to two, and tight leading would collide the vowel marks of one
     line with the letters of the next. */
  line-height:1.5;
  direction:rtl;
  color:var(--paper);           /* 13.83:1 */
  max-width:760px;
  margin:0 auto;
}
/* The attribution line. He is never quoted anonymously. */
.verse-intro{
  font-family:var(--serif);
  font-weight:500;
  font-size:17px;
  color:#B9BFB5;
  margin:0 auto 30px;
  max-width:560px;
}
.verse-en{
  font-family:var(--serif);
  font-weight:500;               /* upright, not italic: a page from a kitab, not a magazine pull-quote */
  font-size:18px;
  color:#B9BFB5;                /* 7.88:1, muted grey-green would fail on ink */
  margin:24px auto 10px;
  max-width:560px;
}
/* Narrator and source on their own lines. A single line wraps mid-phrase and
   splits "may Allah be / pleased with him", which reads carelessly. */
.verse-src{
  font-size:13px;
  color:#C98A78;                /* 5.21:1, the madder red lifted for dark ground */
  margin:0 auto;
  max-width:none;
}
.verse-ref{
  font-size:11.5px;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:#8E9A92;
  margin:6px auto 0;
  max-width:none;
}
/* A Qari's family may print this page. A full ink slab eats a cartridge. */
@media print{
  .verse{background:#fff;padding:48px 24px}
  .verse-ar{color:#000}
  .verse-en{color:#333}
  .verse-src{color:#000}
}

/* ---------- faq ---------- */
.faq-shell{max-width:760px}
.qa{border-bottom:1px solid var(--line)}
.qa summary{
  cursor:pointer;list-style:none;position:relative;
  font-family:var(--serif);font-weight:500;font-size:19px;
  padding:20px 40px 20px 0;
}
.qa summary::-webkit-details-marker{display:none}
/* The plus TURNS INTO the minus instead of being swapped for it. Two hairlines,
   one rotates away. A content: glyph swap can never transition. */
.qa summary::after,.qa summary::before{
  content:"";position:absolute;right:6px;top:50%;
  width:15px;height:2px;background:var(--accent);
  transform:translateY(-50%);
}
.qa summary::before{
  transform:translateY(-50%) rotate(90deg);
  transition:transform .3s cubic-bezier(.16,1,.3,1);
}
.qa[open] summary::before{transform:translateY(-50%) rotate(0deg)}
@keyframes qa-in{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:none}}
.qa[open] p{animation:qa-in .3s cubic-bezier(.16,1,.3,1) both}
.qa p{padding:0 0 20px;color:var(--muted)}

/* ---------- contact ---------- */
.contact{text-align:center}
.contact-shell{max-width:640px}
.contact .kicker{margin-bottom:14px}
.contact-lede{margin:0 auto 30px;color:var(--muted)}
.contact-actions{display:flex;flex-direction:column;align-items:center;gap:16px}
.contact-alt{font-size:15px;color:var(--muted)}

/* ---------- footer ---------- */
/* Footer is LIGHT on purpose. A second dark area would prove the verse band
   was decoration rather than reverence. The sacred band stays the only one. */
.site-foot{background:var(--surface);color:var(--ink);border-top:1px solid var(--line);padding:48px 0}
.foot-row{display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap}
.foot-brand{display:flex;align-items:center;gap:14px}
.foot-name{font-family:var(--serif);font-size:19px;font-weight:500}
.foot-ar{font-family:var(--kufi);font-weight:500;font-size:17px;direction:rtl;color:var(--ink);margin-top:5px}
.foot-sub{font-size:12.5px;color:var(--muted);letter-spacing:.06em}
.foot-line{font-size:14px;color:var(--muted)}

/* ---------- 404 (404.html only) ----------
   Sized so the footer still lands below the fold on a laptop rather than
   floating halfway up an empty page, which is what makes an error page feel
   broken rather than calm. min-height, never a fixed height. */
.lost{display:flex;align-items:center;min-height:66vh;padding:72px 0}
.lost-shell{max-width:640px;text-align:center}
.lost h1{font-family:var(--serif);font-size:clamp(30px,5vw,44px);font-weight:500;line-height:1.15;margin:6px 0 16px}
/* Narrower than the shell so the centred lede breaks into even lines instead
   of dropping one lonely word onto a third line. */
.lost .lede{max-width:520px;margin:0 auto;text-wrap:pretty}
.lost-actions{margin-top:30px}

/* ---------- responsive ---------- */
@media (max-width:900px){
  .hero-grid{grid-template-columns:1fr;gap:24px}
  /* Tablet: the photo stacks under the words. The old rule here also shrank the
     shamsa to 300px, which is NARROWER than the photo in front of it, so the
     frame was completely hidden behind the photo on every tablet. The base
     min(620px,116%) sizing is correct at this width too, so no override. */
  .hero-art{margin-top:8px}
  .about-grid{grid-template-columns:1fr;gap:32px}
  .course-grid{grid-template-columns:1fr 1fr}
  .trust-row{grid-template-columns:1fr 1fr;gap:22px}
}
@media (max-width:820px){
  .nav-toggle{
    display:block;background:none;border:1px solid var(--line);
    border-radius:3px;padding:10px 12px;cursor:pointer;
  }
  .nav-toggle-bar{
    display:block;width:20px;height:2px;background:var(--ink);
    box-shadow:0 6px 0 var(--ink),0 -6px 0 var(--ink);
  }
  .nav-list{
    display:none;position:absolute;top:86px;left:0;right:0;
    background:var(--paper);border-bottom:1px solid var(--line);
    flex-direction:column;padding:18px 24px;gap:16px;align-items:flex-start;
  }
  .nav-list.open{display:flex}
}
@media (max-width:640px){
  .section{padding:64px 0}
  /* Without this the 404 came to 833px against an 820px phone viewport, so an
     error page scrolled by 13px for no reason. It now settles inside one screen. */
  .lost{min-height:58vh;padding:52px 0}
  .hero{padding:64px 0 52px}
  /* The hero art used to be pure decoration, so hiding it on a phone was right.
     It is now the strongest PHOTO on the site, and most of these families are on
     phones, so hiding it would hide the proof the school is real. The photo
     stays, the shamsa behind it goes, since ornament is what costs the space. */
  .hero-art{display:block;margin-top:22px}
  .hero-photo{max-width:100%}
  .course-grid{grid-template-columns:1fr}
  .why-grid{grid-template-columns:1fr}
}

/* ---------- the ayah band ---------- */
/* Quieter than the hadith band below, deliberately. See the comment in the HTML. */
.ayah{
  padding:88px 24px;
  background:color-mix(in srgb, var(--surface) 60%, var(--paper));
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  text-align:center;
}
.ayah-inner{max-width:900px;margin:0 auto}
/* EVERY p IN HERE NEEDS margin-inline:auto, and it is not decoration.
   A global rule at the top of this file caps every paragraph at p{max-width:62ch}.
   text-align:center on the parent centres the TEXT INSIDE the box, it does not
   centre the BOX, so a 62ch box with margin:0 pins itself to the left edge and
   the line lands about 230px left of where it looks like it should. The verse
   reference sat visibly off centre until this was found by measuring a render,
   not by reading the css. Any new p added to this band needs the same. */
.ayah-ar{
  font-family:'Amiri Quran',var(--arabic),serif;
  font-weight:400;
  /* Uthmani marks sit high and low off the baseline, so this needs more leading
     than the hadith line does, never less. */
  font-size:clamp(30px,4.6vw,44px);
  line-height:2.05;
  color:var(--ink);
  margin:0 auto 26px;
}
.ayah-en{
  font-family:var(--serif);
  font-size:clamp(17px,2vw,20px);
  line-height:1.7;
  color:var(--ink);
  max-width:640px;
  margin:0 auto 14px;
}
.ayah-ref{
  font-size:12.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--rubric);font-weight:600;margin:0 auto;
}


/* ---------- the recitation ---------- */
.recite-shell{display:grid;grid-template-columns:1fr .85fr;gap:56px;align-items:center}
.recite-frame{margin:0;justify-self:center}
.recite-frame video{
  /* The source is now 1080x1920, upscaled 4x from the 478px WhatsApp copy with
     the same Real-ESRGAN pass the photos use, then brought down to 1080. So the
     360px cap has real pixels behind it even on a 3x phone screen, which the
     478px original did not. Measured: the upscale is also LESS noisy frame to
     frame than the source, 0.161 against 0.470 mean change in a still region,
     so it does not shimmer. Raise this cap only if the source grows again. */
  width:100%;max-width:360px;height:auto;display:block;
  border-radius:6px;border:1px solid var(--line);background:var(--ink);
  box-shadow:0 18px 34px -24px rgba(27,43,37,.5);
}
@media (max-width:900px){.recite-shell{grid-template-columns:1fr;gap:28px}}

.recite-what{font-size:15px;color:var(--muted);margin-top:14px;max-width:46ch}
