/* ============================================================================
   Quran Study -- base stylesheet

   One file, read top to bottom: tokens, then elements, then components in the
   order they appear on the page, then the single width breakpoint at 600px.
   Everything is served from this origin; the content policy is default-src
   'self', so there are no font, script or image requests to anywhere else.
   ========================================================================= */


/* ----------------------------------------------------------------------------
   1. Tokens -- light (the default)

   Colours live here and nowhere else, so a theme change is one edit to this
   block. The paper tones are warm rather than neutral: the page should read
   like a printed leaf, not like a dialog box.
   ------------------------------------------------------------------------- */
:root {
  /* Surfaces, from the page ground up to a raised card. */
  --paper:        #faf7f2;
  --paper-raised: #ffffff;
  --paper-sunk:   #f2ece2;
  --rule:         #e3dacd;

  /* Text, in three weights of presence. --ink-faint is the quietest tone that
     still clears 4.5:1 on --paper; nothing lighter is used for real text. */
  --ink:       #2b2621;
  --ink-soft:  #57504a;
  --ink-faint: #756b60;

  /* A single restrained accent: the green of a bound endpaper. */
  --accent:        #2f5d50;
  --accent-strong: #24483e;
  --accent-tint:   #e7efeb;
  /* Half a step short of --accent-tint, for a state that must be visible and
     must also lose to one. The word under the pointer takes this; the word
     being recited takes the tint, and stays the louder of the two even when
     the pointer is resting on it.

     Not chosen by eye. It is the midpoint between --paper and --accent-tint,
     which measures 1.048 against the page where the tint measures 1.095: half
     the presence, by construction rather than by taste. A first attempt sat at
     1.020 and was nearly invisible on a laptop screen. */
  --accent-wash:   #f0f3ee;

  /* THE HIGHLIGHTER. Not a third member of the accent family and not a state
     colour: it marks a RUN OF TEXT the reader is hunting for inside somebody
     else's prose -- the verse a narration cites, inside fifteen hundred words
     of narration -- and it is the one job in this palette that wants to be
     found from across the page rather than noticed once you are on it.

     The accent's own mark was tried first and failed at exactly that. A 2px
     edge under --accent-tint is a quiet, low-AREA treatment, which is right for
     a studied word sitting alone in a panel and wrong for one phrase in a wall
     of running text. The lesson is the one the ring taught at 10.1:1 in section
     13: what was missing there was area, not contrast.

     #f9d423 holds --ink at 10.3:1, so the marked words stay as readable as the
     prose around them, and it stands 1.36:1 off --paper -- the widest of the
     candidates measured. Yellow on cream is never going to separate by
     luminance; it separates by HUE, which is why the most saturated of them
     won rather than the lightest. */
  --mark:      #f9d423;
  --mark-ink:  #2b2621;

  /* CAUTION. Not an error colour and not for errors: it marks the ONE state
     where a reader has wandered from what they asked for and there is a way
     back -- the lexicon open at a root the word does not belong to, and the
     reading page moved to a verse the reader followed. Both are the app
     working, so this nudges and never alarms.

     It is the tajweed qalqalah red, which this palette already owns and the
     word study panel already draws segments in, pulled to a ground and an ink
     rather than invented: a scheme with one warm red in it should not gain a
     second. #9c4030 on #f7e8e3 measures 7.4:1, so the label is comfortably
     readable rather than merely legible at the size it is used. */
  --caution:       #9c4030;
  --caution-tint:  #f7e8e3;

  --shadow-soft: 0 1px 2px rgba(43, 38, 33, 0.04), 0 8px 24px rgba(43, 38, 33, 0.05);

  /* Type. System stacks only -- no webfont is downloaded. The serif carries all
     reading text; the sans is reserved for labels, navigation and metadata. */
  --font-serif: ui-serif, Georgia, "Iowan Old Style", "Palatino Linotype",
                "Book Antiqua", "Times New Roman", serif;
  --font-sans:  ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
                "Helvetica Neue", Arial, sans-serif;
  --font-arabic: "Amiri", "Scheherazade New", "KFGQPC Uthmanic Script HAFS",
                "Traditional Arabic", "Segoe UI", "Geeza Pro", "Noto Naskh Arabic", serif;

  /* Measure and rhythm. */
  /* Border weights. Structure comes from hairlines, never from shadows, so the
     three weights below are the whole vocabulary for separating things. */
  --rule-soft:   #efe7da;
  --rule-strong: #cdbfab;
  --hair: 1px;
  --emph: 2px;

  /* Type scale. Ratio is a slow 1.2 so a study page has many quiet steps rather
     than a few loud ones. */
  --fs-caption: 0.78rem;
  --fs-label:   0.68rem;
  --fs-body-sm: 0.88rem;
  --fs-body:    1rem;
  --fs-body-lg: 1.08rem;
  --fs-h3:      1.2rem;
  --fs-h2:      1.45rem;
  --fs-h1:      1.85rem;
  --fs-display: 2.5rem;

  --lh-tight:   1.2;
  --lh-heading: 1.3;
  --lh-body:    1.55;
  --lh-reading: 1.7;

  /* Spacing. A 4px base, doubling slowly. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;

  --radius-control: 10px;
  --radius-pill: 999px;

  /* Motion. Every duration is clamped to nothing by the reduced-motion guard in
     section 18, so these are the "if allowed" values. */
  --dur-fast: 90ms;
  --dur:      140ms;
  --dur-slow: 260ms;
  --ease-calm: cubic-bezier(0.32, 0.72, 0, 1);

  --focus-width: 2px;
  --focus-offset: 2px;

  /* Arabic metrics. Both line heights are tuned by eye and must not be
     "corrected": the QCF page faces carry the printed mushaf's own tall
     metrics, so the leading that suits Amiri gaps them apart. */
  --ar-scale: 1;
  --lh-arabic-typeset: 2.4;
  --lh-arabic-mushaf: 1.8;

  /* Tajweed, thirteen rules. Named for the rule, never the colour.
     Retuned from the conventional recitation-mushaf palette for a warm light
     ground: the same hue families a reader already recognises, at a saturation
     that does not shout against parchment. Colour is NEVER the sole carrier;
     section 20 of quran.css gives every family a second, non-colour channel. */
  --tj-silent:           #786f61;
  --tj-madd-normal:      #3f6fb5;
  --tj-madd-permissible: #2f4fa8;
  --tj-madd-necessary:   #21327e;
  --tj-qalqalah:         #b3352c;
  --tj-ikhfa:            #7d3d92;
  --tj-ikhfa-shafawi:    #a53f96;
  --tj-idgham-ghunnah:   #1f7a63;
  --tj-idgham-plain:     #2f7a3a;
  --tj-idgham-shafawi:   #4f7a24;
  --tj-idgham-close:     #586b55;
  --tj-iqlab:            #1d7895;
  --tj-ghunnah:          #a8591b;

  --measure: 42.5rem;
  --wrap: 68rem;
  --gutter: 1.25rem;
  --radius: 14px;

  /* The mushaf's own palette, corrected. Not a theme switch -- this is the
     standing default, and section 2 outranks it because a bare :root weighs
     0,1,0 against its 0,2,0. The V4 faces paint their base letterform from
     inside the font, where CSS `color` never reaches, and palette 0 sets it to
     #000000 against the --ink above: colder and blacker than every other word
     on the page. qcf-pages.css keeps palette 0 and moves only that entry and
     the two travelling with it.

     The ink value is repeated as a literal in scripts/build_qcf_css.py, because
     @font-palette-values is an at-rule with no element beneath it to resolve a
     custom property against. Retune --ink and regenerate; a test fails if the
     two drift. */
  font-palette: --qs-mushaf-light;
}


/* ----------------------------------------------------------------------------
   2. Tokens -- dark

   Values, and one property. No rule below this block asks which theme is
   running, and the property at the end of it is what keeps that true for the
   mushaf: see the note beside it.
   ------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:        #16130f;
    --paper-raised: #1e1a16;
    --paper-sunk:   #100e0c;
    --rule:         #332d26;

    --ink:       #ece4d8;
    --ink-soft:  #bcb0a0;
    --ink-faint: #9a8f7f;

    --accent:        #86b8a5;
    --accent-strong: #a5cfbe;
    --accent-tint:   #22302b;
    --accent-wash:   #1c221d;

    /* Dark ink on the yellow here too, rather than the page's light ink: a
       highlighter is a bright ground whichever way the page runs, and inverting
       it would make the mark a dark hole in dark prose. Pulled down from the
       light value so it does not glare off the desk -- 7.5:1 for the ink on it,
       and 9.3:1 against --paper, so it is if anything easier to find here than
       in the light. */
    --mark:      #e0b12e;
    --mark-ink:  #2b2621;
    /* The qalqalah red's own dark value, on a ground lifted off the
       ink the same distance --accent-tint sits off it. 8.1:1. */
    --caution:       #e8877d;
    --caution-tint:  #35211d;

    --rule-soft:   #262019;
    --rule-strong: #4a4136;

    /* Tajweed in dark. Lifted and desaturated so no rule glows against the
       dark desk while the hue families stay recognisable. */
    --tj-silent:           #8a8175;
    --tj-madd-normal:      #8fb2ee;
    --tj-madd-permissible: #9aa8f0;
    --tj-madd-necessary:   #a8b0e8;
    --tj-qalqalah:         #e8877d;
    --tj-ikhfa:            #c79ad8;
    --tj-ikhfa-shafawi:    #dd9ad0;
    --tj-idgham-ghunnah:   #7cc7ae;
    --tj-idgham-plain:     #8ac78f;
    --tj-idgham-shafawi:   #a6c77a;
    --tj-idgham-close:     #9a9184;
    --tj-iqlab:            #7cc2dd;
    --tj-ghunnah:          #e0a06a;

    --shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.28);

    /* The only declaration in this block that is not a token, and the only way
       the mushaf can be reached at all. The V4 page faces are COLR/CPAL colour
       fonts: their letterforms are painted from a palette inside the font and
       CSS `color` does not apply, so until 2026-08-20 the Arabic stayed black
       here while every other word on the page turned over. The faces ship a
       dark palette of their own; qcf-pages.css binds it to this name.

       It sits on :root because font-palette inherits. That is what spares
       quran.css and qcf-pages.css from having to ask which theme is running --
       the alternative was a media query around 604 generated blocks. A face
       with no block under this name resolves it to `normal`, so the V2 set,
       Amiri and the UI stack are all untouched, and a browser without
       font-palette ignores the line and renders as it did before. */
    font-palette: --qs-mushaf-dark;
  }
}

/* ----------------------------------------------------------------------------
   2b. Tokens -- dark, chosen

   The same declarations as section 2, for a reader who asked for dark on a
   device that did not. They have to be written twice because CSS cannot OR a
   media query with a selector, and there is no third condition to fold them
   into: the block above answers "this device prefers dark and the reader has
   not overridden", this one answers "the reader chose dark".

   Do not edit either block alone. tests/test_theme.py compares them
   declaration by declaration and fails if they drift, which is the only thing
   making this duplication safe. Both are generated from one source by
   scripts-free hand edits at your peril; change one, copy it to the other, run
   the test.

   It comes second on purpose. Both selectors weigh 0,2,0, so source order is
   what makes an explicit choice beat the device's preference.
   ------------------------------------------------------------------------- */
:root[data-theme="dark"] {
    --paper:        #16130f;
    --paper-raised: #1e1a16;
    --paper-sunk:   #100e0c;
    --rule:         #332d26;

    --ink:       #ece4d8;
    --ink-soft:  #bcb0a0;
    --ink-faint: #9a8f7f;

    --accent:        #86b8a5;
    --accent-strong: #a5cfbe;
    --accent-tint:   #22302b;
    --accent-wash:   #1c221d;

    /* Dark ink on the yellow here too, rather than the page's light ink: a
       highlighter is a bright ground whichever way the page runs, and inverting
       it would make the mark a dark hole in dark prose. Pulled down from the
       light value so it does not glare off the desk -- 7.5:1 for the ink on it,
       and 9.3:1 against --paper, so it is if anything easier to find here than
       in the light. */
    --mark:      #e0b12e;
    --mark-ink:  #2b2621;
    /* The qalqalah red's own dark value, on a ground lifted off the
       ink the same distance --accent-tint sits off it. 8.1:1. */
    --caution:       #e8877d;
    --caution-tint:  #35211d;

    --rule-soft:   #262019;
    --rule-strong: #4a4136;

    /* Tajweed in dark. Lifted and desaturated so no rule glows against the
       dark desk while the hue families stay recognisable. */
    --tj-silent:           #8a8175;
    --tj-madd-normal:      #8fb2ee;
    --tj-madd-permissible: #9aa8f0;
    --tj-madd-necessary:   #a8b0e8;
    --tj-qalqalah:         #e8877d;
    --tj-ikhfa:            #c79ad8;
    --tj-ikhfa-shafawi:    #dd9ad0;
    --tj-idgham-ghunnah:   #7cc7ae;
    --tj-idgham-plain:     #8ac78f;
    --tj-idgham-shafawi:   #a6c77a;
    --tj-idgham-close:     #9a9184;
    --tj-iqlab:            #7cc2dd;
    --tj-ghunnah:          #e0a06a;

    --shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.28);

    /* The only declaration in this block that is not a token, and the only way
       the mushaf can be reached at all. The V4 page faces are COLR/CPAL colour
       fonts: their letterforms are painted from a palette inside the font and
       CSS `color` does not apply, so until 2026-08-20 the Arabic stayed black
       here while every other word on the page turned over. The faces ship a
       dark palette of their own; qcf-pages.css binds it to this name.

       It sits on :root because font-palette inherits. That is what spares
       quran.css and qcf-pages.css from having to ask which theme is running --
       the alternative was a media query around 604 generated blocks. A face
       with no block under this name resolves it to `normal`, so the V2 set,
       Amiri and the UI stack are all untouched, and a browser without
       font-palette ignores the line and renders as it did before. */
    font-palette: --qs-mushaf-dark;
}


/* ----------------------------------------------------------------------------
   3. Elements
   ------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  color-scheme: light dark;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* THE SCROLLBAR IS FURNITURE, NOT CONTENT. The user agent paints it from
     color-scheme, which on Windows is a heavy mid-grey bar standing at the
     edge of a page whose whole palette is warm paper -- the loudest vertical
     line on the screen, and beside an open panel it is also the thing a
     reader is least sure the meaning of. --rule is the hairline this app
     already uses for a component's own edge, and it is theme-aware, so one
     declaration is right on paper and on ink. It INHERITS, deliberately: the
     panel's own scrollers should not each be a different grey.

     `thin` where it is understood; the colour alone lands everywhere else. */
  scrollbar-color: var(--rule) transparent;
  scrollbar-width: thin;
}

/* An explicit choice has to reach the furniture the user agent paints for
   itself -- scrollbars, the caret, form controls, the date picker -- which
   follows color-scheme and not any colour of ours. Declared "light dark" above,
   it tracks the device, so a reader who chose light on a dark phone would read
   light paper past a dark scrollbar. These two say which one is actually
   running; without a choice the pair above still answers, as it always has. */
html[data-theme="light"] { color-scheme: light; }
html[data-theme="dark"] { color-scheme: dark; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-serif);
  font-size: 1rem;
  line-height: 1.65;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  margin: 0;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.005em;
}

p { margin: 0; }

ul, ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

a {
  color: var(--accent-strong);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover { color: var(--accent); }

em { font-style: italic; }

/* Work titles. Declared for the same reason em is: the reset flattens it. */
cite { font-style: italic; }

::selection {
  background: var(--accent-tint);
  color: var(--ink);
}


/* ----------------------------------------------------------------------------
   4. Skip link and focus

   The skip link sits off-screen until it takes focus, then lands in the top
   corner ahead of the masthead. Focus is styled once, for everything.
   ------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -4rem;
  /* Above every layer the header itself uses: the bar's own 92 and the search
     column's 96. 10 was written when nothing in the masthead was positioned,
     and it stopped being true the day .quran .masthead took a z-index to clear
     the tafsir panel -- so on every Qur'an page, which is most of the site, the
     first thing a keyboard reaches landed BEHIND the bar it offers to skip.
     Measured 2026-08-25 with elementFromPoint at the link's own centre: the
     masthead answered the pointer on /quran and /quran/<n>, the landing page
     answered correctly, and the comment above this block had said "ahead of the
     masthead" throughout. The way past everything cannot be under any of it. */
  z-index: 97;
  padding: 0.6rem 1rem;
  border-radius: 0 0 8px 8px;
  background: var(--accent-strong);
  color: var(--paper);
  font-family: var(--font-sans);
  font-size: 0.9rem;
  text-decoration: none;
  transition: top 120ms ease-out;
}

.skip-link:focus {
  top: 0;
  color: var(--paper);
}

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


/* ----------------------------------------------------------------------------
   5. Layout primitives
   ------------------------------------------------------------------------- */
.wrap {
  width: min(var(--wrap), 100% - (var(--gutter) * 2));
  margin-inline: auto;
}

.section-heading {
  font-size: clamp(1.35rem, 1.2rem + 0.7vw, 1.7rem);
  color: var(--ink);
}

.section-heading--centred { text-align: center; }

/* The section's answer, in one line, and it is the reference page's chief
   visual cue.

   It was soft-grey body copy of two sentences until 2026-08-24, when that page
   was cut from about 1,650 words to about 700 on the owner's judgement that a
   reader glances at it rather than reads it. What survives a glance is a
   heading and the line under it, so that line was made large enough to be worth
   stopping on and short enough to deserve it. Full --ink and the hero
   standfirst's size, because it is no longer supporting a paragraph -- there is
   no paragraph -- it is the section in one sentence. */
.section-intro {
  max-width: var(--measure);
  margin-top: 0.55rem;
  font-size: clamp(1.14rem, 1.05rem + 0.45vw, 1.34rem);
  line-height: 1.45;
  color: var(--ink);
  text-wrap: pretty;
}

/* Small sans label used above the specimen's key, over a page's title, and on
   the reference page's jump list. */
.specimen__label,
.page-nav__label,
.eyebrow {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-strong);
}


/* ----------------------------------------------------------------------------
   6. Buttons

   Two, and they are a pair: same height, same pill radius, same sans face, so
   the eye reads them as one control with two settings rather than as a button
   and a link that happen to be adjacent.

   Only --primary is filled. The green is this site's single accent and the
   masthead's gateway already spends it; a second filled button beside it would
   give a reader two objects of equal weight and no reading of which is the
   point. --ghost carries the same accent as a hairline and a word.

   The height matches .masthead__cta deliberately. The two are the same offer in
   two places, and a reader who has seen one should recognise the other.
   ------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding-inline: var(--space-5);
  border: var(--hair) solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  white-space: nowrap;
}

.btn--primary {
  border-color: var(--accent-strong);
  background: var(--accent);
  color: var(--paper-raised);
}

.btn--primary:hover {
  background: var(--accent-strong);
  color: var(--paper-raised);
}

.btn--ghost {
  border-color: var(--rule-strong);
  background: transparent;
  color: var(--accent-strong);
}

.btn--ghost:hover {
  border-color: var(--accent);
  background: var(--accent-tint);
  color: var(--accent-strong);
}

/* Wrapping is the point: at 320px the two do not fit on one row, and a row that
   scrolls sideways is worse than a row that becomes a column. */
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: 1.6rem;
}


/* ----------------------------------------------------------------------------
   7. Masthead
   ------------------------------------------------------------------------- */
/* THE BAR MEASURES ITSELF, because on a reading page it is not as wide as the
   window and every rule about it used to think it was.

   The masthead is position: sticky, which is IN FLOW, and it sits inside a
   <body> that a panel pads out of its way -- padding-inline-end: var(--qs-panew).
   So opening a panel genuinely halves this box while the viewport it is
   measured against does not move. Recorded on 2026-08-20, when the fault first
   showed at 768px and the answer was to raise the split's breakpoint to 62rem;
   the breakpoint was right and it was pointed at the wrong box, so the fault
   moved rather than went. Measured again 2026-08-25: at a 992px window with a
   panel at the shipped half this bar is 496px, the field's track resolves to
   63px, and the keyboard pill overhung it onto the All surahs link.

   Container queries were REJECTED for this in 2026-08-20 on the single ground
   that they were not used anywhere in this project, with the revisit written
   into the same entry -- "worth revisiting if that fault appears somewhere the
   breakpoint cannot reach". Both halves of that are now met: the fault is in a
   box no @media can see, and there are two containers in quran.css already,
   wstudy-pane and hadith-pane.

   Named rather than anonymous, the convention hadith-pane states: a future
   container inside this one cannot then capture these queries by accident.

   Nothing is MOVED into a container query. Every @media rung stays where it
   is, so no engine loses a rule it has today and no @supports guard is needed;
   the container rungs only tighten what the viewport rungs already handle when
   nothing is open. The duplication is deliberate and a test holds the two
   copies to the same declarations.

   Safe to contain in the inline axis because this element's width never comes
   from its contents -- it is a normal-flow block whose inline size is the body
   content box, the same argument .wstudy__panes makes for itself. Size
   containment here is INLINE only, so header.js goes on measuring the height
   it reserves. contain: layout comes with it and makes this a containing block
   for absolute descendants, which changes nothing: .qsearch__icon and
   .qsearch__under resolve against .qsearch, .qs-panel against
   .masthead__actions and .contents__list against .surahtoc, all of them
   positioned and all of them inside. The one fixed thing that would have
   broken, .surahtuck, is deliberately OUTSIDE this element already. */
.masthead {
  container: masthead / inline-size;
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}

.masthead__inner {
  display: flex;
  /* Two children now, the wordmark and the way in, and they belong at the two
     ends of one row at every width. Wrapping was there for the section links
     that used to sit between them; left in place it put Read Qur'an on a
     second row, at the LEFT, on a 320px screen. Measured: the wordmark is
     143px, the button 114px and the old 24px gap made 281px of a 280px row, so
     it wrapped by a single pixel. */
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  /* The gap gives way before the row does. 24px from 600px up, which is what
     it has always been, tightening to about 13px on the narrowest phone. The
     wide layout is unchanged and the narrow one gains the pixels it was short
     by, without a second breakpoint in a file that defends having one.

     4cqi and not 4vw since 2026-08-25. A viewport unit inside a bar that is
     measured by its container is the same fault the container was added for,
     one size down: with a panel open the gap went on spending a wide window's
     24px in a 636px bar. cqi asks the bar. */
  gap: 0.5rem clamp(0.75rem, 4cqi, 1.5rem);
  padding-block: 1rem;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  /* Lets the name give way rather than the row. With the gap fluid this should
     never be reached on any real phone; it is here so that a narrower screen,
     or a wider system face than the one this was measured in, degrades by
     shortening the name instead of moving the button people came to press. */
  min-width: 0;
  color: var(--ink);
  text-decoration: none;
}

.wordmark__mark { color: var(--accent); flex: none; }

/* The landing page's row, once the search moved into it on 2026-08-24.

   The same three-track formula the Qur'an pages use, and deliberately the same
   numbers: a reader crossing from here to /quran should not see the field jump
   width or the wordmark change place. It is repeated rather than shared
   because the landing page does not load quran.css, which is the same reason
   section 23 holds the bar's own styles.

   max-content floors on the flanks rather than 0, for the reason recorded
   beside the Qur'an copy: with minmax(0, 1fr) the tracks shrink below their
   contents and "Quran Study" wraps onto two lines, taking the row from 76px to
   88px. The floors also keep the centring honest -- equal 1fr tracks resolve
   equal wherever there is room.

   24rem is the cap that answers the objection this move overruled. A field
   free to fill the middle would run up against the filled CTA and the two
   would read as one cluster of equal weight; stopped at 24rem it keeps a gap
   nothing has to be said about. */
.landing .masthead__inner {
  display: grid;
  /* Narrow first, because section 17 is a MIN-width block and this file keeps
     it as its only width query. Here the wordmark is its mark alone (rule
     below section 8), so three simple tracks fit on one row and the field
     takes whatever the mark and the button leave -- about 195px at 360px,
     measured, which is what the all-surahs masthead already ships at this
     size. The centred formula arrives with the rest of the wide layout. */
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
}

/* Two tracks when there is no field to put in the middle one. While
   QURAN_UNIVERSAL_SEARCH is dark this page renders no bar at all -- it has
   nothing to fall back to, unlike /quran -- and three tracks with two children
   auto-place the CTA into the MIDDLE, stranded mid-row with a gap either side.
   The Qur'an pages hit exactly this and answer it by naming their tracks per
   page; here the flag decides, so the selector asks the DOM instead.

   :has() and not a second body class, because this file already depends on it
   and the alternative is a template flag whose only reader is a stylesheet. */
.landing .masthead__inner:not(:has(.qsearch)) {
  grid-template-columns: 1fr auto;
}

.landing .wordmark { white-space: nowrap; }

.wordmark__text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 1.06rem;
  font-weight: 600;
  letter-spacing: 0.01em;
}

/* .masthead__nav was here. The page-local anchors it styled were removed on
   2026-08-19 and the block in base.html left empty, so nothing carries the
   class. With them gone the flex row is the wordmark and the actions, which
   space-between puts at the two ends at every width, phone included. */

.masthead__actions {
  position: relative;      /* the settings panel drops from here */
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
}

/* THE FILLED BUTTON KEEPS ITS DISTANCE FROM THE FIELD.

   One column gap is enough between a field and a text link; it is not enough
   between a field and the only filled control on the site. Where the row has
   slack the two are far apart anyway -- 238px at 1280 -- but the moment the
   tracks tighten they close to the gap alone, 24px, and the owner read that as
   the pair being crowded. 1rem on top of the gap makes the floor 40px, which
   is the same distance the wordmark keeps from the field on the other side
   once its own track is at its floor.

   Landing only: it is the one masthead whose actions hold a filled CTA. The
   surah page's actions are a text link and an outlined button, which the gap
   already separates properly. */
.landing .masthead__inner > .masthead__actions {
  margin-inline-start: var(--space-4);
}

/* The display settings, sitting beside the gateway button and matching its
   weight. Outlined rather than filled: the doctrine allows exactly one filled
   accent control per view, and that is the gateway. This is the same size and
   the same shape so the pair reads as one group. */
.masthead__display {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding-inline: var(--space-4);
  border: var(--hair) solid var(--rule-strong);
  border-radius: var(--radius-pill);
  background: var(--paper-raised);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  cursor: pointer;
}

/* The rule above sets display, which would otherwise defeat the attribute that
   keeps the control out of a page where no script is running to open it. */
.masthead__display[hidden] { display: none; }

.masthead__display:hover {
  border-color: var(--accent);
  color: var(--accent-strong);
}

.masthead__display[aria-expanded="true"] {
  border-color: var(--accent);
  background: var(--accent-tint);
  color: var(--accent-strong);
}

.masthead__display:focus-visible {
  outline: var(--focus-width) solid var(--accent-strong);
  outline-offset: var(--focus-offset);
}

/* A 44px target rather than the 19px the text alone gave it. It sits beside
   the display button and the gateway, both already 44px, so the row is that
   tall whatever this does and the height is free at every width. */
.masthead__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  color: var(--ink-soft);
  text-decoration: none;
  white-space: nowrap;
}

.masthead__link:hover { color: var(--accent-strong); }

.masthead__gear { flex: none; color: var(--ink-faint); }
.masthead__display:hover .masthead__gear,
.masthead__display[aria-expanded="true"] .masthead__gear { color: currentColor; }


/* The gateway into the Qur'an, and the only filled control in the masthead. It
   is the one thing on the landing page that is an action rather than a link, so
   it is the one thing that carries the accent as a fill. */
.masthead__cta {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--space-4);
  border: var(--hair) solid var(--accent-strong);
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--paper-raised);
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  white-space: nowrap;
}

.masthead__cta:hover {
  background: var(--accent-strong);
  color: var(--paper-raised);
}

.masthead__cta:focus-visible {
  outline: var(--focus-width) solid var(--accent-strong);
  outline-offset: var(--focus-offset);
}


/* ---------------------------------------------------------------------------
   The account chip

   Here rather than in account.css because it is drawn on every page, and
   account.css is loaded only by the account screens themselves.

   A circle of initials and not a name: the row already holds a wordmark, up to
   two page actions and the gateway, and at 320px that row was 281px wide in a
   280px space before the gap became fluid (see the note at the top of this
   section). A 40px disc is the smallest honest control that still reads as
   "you", and it costs the row 40px at every width instead of a name's worth.

   Outlined, never filled. The gateway above is the one filled control in the
   masthead and this sits directly beside it; two fills would make the row read
   as two competing actions rather than one.
   --------------------------------------------------------------------------- */

.masthead__account {
  position: relative;
  flex: none;
}

/* The disclosure triangle a <summary> draws by default, removed in both
   spellings: Safari needs the pseudo-element, everything else the property. */
.masthead__chip::-webkit-details-marker { display: none; }

.masthead__chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 40px;
  block-size: 40px;
  border: var(--hair) solid var(--rule-strong);
  border-radius: var(--radius-pill);
  background: var(--paper-raised);
  color: var(--accent-strong);
  list-style: none;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease-calm);
}

.masthead__chip:hover,
.masthead__account[open] > .masthead__chip { border-color: var(--accent); }

.masthead__chip:focus-visible {
  outline: var(--focus-width) solid var(--accent-strong);
  outline-offset: var(--focus-offset);
}

.masthead__initials {
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
}

/* Anchored to .masthead__actions, which is already position: relative for the
   Display panel. Pinned to the inline end so it opens inward from the right
   edge and cannot push the viewport sideways. */
.masthead__menu {
  position: absolute;
  inset-inline-end: 0;
  inset-block-start: calc(100% + var(--space-2));
  z-index: 20;
  min-inline-size: 15rem;
  padding: var(--space-3);
  border: var(--hair) solid var(--rule);
  border-radius: var(--radius-control);
  background: var(--paper-raised);
  box-shadow: var(--shadow-soft);
}

.masthead__whoami {
  margin: 0 0 var(--space-2);
  padding-block-end: var(--space-2);
  border-block-end: var(--hair) solid var(--rule-soft);
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  line-height: var(--lh-body);
  color: var(--ink-faint);
}

.masthead__whoami strong {
  display: block;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--ink);
}

.masthead__whoami span { overflow-wrap: anywhere; }

.masthead__menulink,
.masthead__menubtn {
  display: flex;
  align-items: center;
  inline-size: 100%;
  min-block-size: 44px;
  padding-inline: var(--space-2);
  border: 0;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--ink-soft);
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  text-align: start;
  text-decoration: none;
  cursor: pointer;
}

.masthead__menulink:hover,
.masthead__menulink:focus-visible,
.masthead__menubtn:hover,
.masthead__menubtn:focus-visible {
  background: var(--accent-wash);
  color: var(--accent-strong);
}

.masthead__menuform {
  margin: var(--space-2) 0 0;
  padding-block-start: var(--space-2);
  border-block-start: var(--hair) solid var(--rule-soft);
}


/* Below 600px the wordmark is its mark alone, so the field keeps a usable
   width. Measured on a 360px row: the mark is 22px and the CTA 114px, which
   with two fluid gaps leaves about 195px of field -- the width the all-surahs
   masthead already ships at this size.

   Hidden the accessible way and NOT with display:none. The span is the link's
   only text and the mark beside it is aria-hidden, so removing the span from
   the accessibility tree would leave the home link with no name at all. The
   Qur'an pages learned this; the note is repeated because the rule is. */
.landing .wordmark__text {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* ----------------------------------------------------------------------------
   8. Hero
   ------------------------------------------------------------------------- */
.hero__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: clamp(1.75rem, 1rem + 3vw, 3rem);
  padding-block: clamp(2.25rem, 1.5rem + 3.5vw, 3.75rem) clamp(2rem, 1.5rem + 3vw, 3.5rem);
}

/* The two columns part company on their own flex basis rather than at a width
   query: below roughly 850px the pair can no longer both hold their basis, so
   they wrap. That keeps section 17 the only width breakpoint in this file.

   Copy first in the source, copy first on the page, copy first when the two
   stack. There is no ordering property here and there should not be one: the
   visual order and the reading order are the same order. */
.hero__copy {
  flex: 1 1 27rem;
  min-width: 0;
}

.hero__figure {
  flex: 1 1 22rem;
  min-width: 0;
  margin: 0;
}

/* The headline is one short line now, so it can carry a larger size than the
   long one it replaced without running past the foot of the screenshot. */
.hero__title {
  margin-top: 0.9rem;
  font-size: clamp(2rem, 1.4rem + 2.1vw, 2.9rem);
  line-height: 1.14;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

/* The standfirst: presence between the headline and the list, carried by size
   rather than by weight or colour alone. It keeps full --ink, which is what
   separates it from the softer rows beneath it. Since 2026-08-28 it also ends
   on the colon that introduces those rows, the .lede that used to do that
   having been merged into it. */
.hero__dek {
  max-width: var(--measure);
  margin-top: 1rem;
  font-size: clamp(1.14rem, 1.05rem + 0.45vw, 1.34rem);
  line-height: 1.45;
  color: var(--ink);
  text-wrap: pretty;
}

/* The sources, one to a line. This list carried hairline separators and no
   markers until 2026-08-20, on the reasoning that a bullet is an emphasis dot
   and the rule line is this project's way of dividing things. The rules did
   divide the rows, but nothing said "list": the block read as stacked
   sentences, with the left edge of every line flush against the paragraphs
   above it. Markers and a hanging indent replace them. The type sits one step
   below the standfirst's and keeps --ink-soft, so the sentence above and the
   list read as one passage rather than as copy with a widget dropped into it.
   The fold's trigger shares this size for the same reason. */
.hero__sources {
  max-width: var(--measure);
  margin: 1.1rem 0 0;
  padding: 0;
  list-style: none;
  font-size: clamp(1.02rem, 0.98rem + 0.25vw, 1.14rem);
  line-height: 1.6;
  color: var(--ink-soft);
}

/* A hanging indent by absolute positioning, not by flex. Flex was tried first
   and was wrong: a flex container blockifies every inline child, so the name,
   the cited link and the clause following it each became a separate column and
   the row read across in pieces instead of as a sentence. Absolute positioning
   leaves the text in normal inline flow, and a wrapped line still aligns under
   the text rather than under the marker. */
.hero__sources li {
  position: relative;
  padding-left: 1.3rem;
  padding-block: 0.3rem;
}

/* A hollow ring rather than a solid dot: it marks the line without carrying the
   weight of an emphasis mark, which is what the hairline separators here were
   originally written to avoid. 7px on a border-box, so the 1px accent stroke
   leaves a 5px counter and the marker reads lighter than it measures. Half a
   line box down, less half its own height, so it sits on the optical centre of
   the first line whatever the clamped font-size resolves to. */
.hero__sources li::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(0.3rem + 0.8em - 0.22rem);
  width: 0.44rem;
  height: 0.44rem;
  border: 1px solid var(--accent-strong);
  border-radius: 50%;
}

/* Forced colours keeps borders and forces their colour, so the ring survives
   on its own. Stated anyway because the rule this replaced painted a
   background, which under forced colours would fill the counter and turn the
   ring back into the solid dot it is meant not to be. */
@media (forced-colors: active) {
  .hero__sources li::before {
    background: transparent;
    border-color: CanvasText;
  }
}


/* The fold under the four open rows. Styled here rather than borrowing the
   reading page's .surahtoc__trigger, which is the same control in the same
   idiom but lives in quran.css and this page does not load that file.

   The trigger is a pressable, so it may spend the accent; the rows it reveals
   are not, so they may not. That is the whole colour decision. */
.hero__more {
  max-width: var(--measure);
  margin-top: 0.35rem;
}

/* list-style: none and the -webkit- rule are both needed: Safari draws the
   disclosure triangle from a pseudo-element the standard property does not
   reach. The chevron below is the marker, and it has to be the only one. */
.hero__more-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-block-size: 44px;
  font-size: clamp(1.02rem, 0.98rem + 0.25vw, 1.14rem);
  line-height: 1.6;
  color: var(--accent-strong);
  cursor: pointer;
  list-style: none;
}

.hero__more-trigger::-webkit-details-marker { display: none; }

/* Underline on hover rather than a background or a border. The row it sits
   under carries neither, and a control that grows a box on hover reads as a
   button dropped into a passage of prose. */
.hero__more-trigger:hover > span {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.hero__more-trigger:focus-visible {
  outline: var(--focus-width) solid var(--accent-strong);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-control);
}

.hero__more-chev {
  flex: none;
  transition: transform var(--dur) var(--ease-calm);
}

.hero__more[open] .hero__more-chev { transform: rotate(180deg); }

/* The revealed rows are the same list at the same measure and the same type,
   so opening the fold reads as the list carrying on rather than as a second
   block arriving. The top margin is smaller than .hero__sources' own because
   the trigger's 44px target has already spent the gap. */
.hero__sources--folded {
  margin-top: 0.15rem;
}

/* ----------------------------------------------------------------------------
   9. The specimen -- an illustration of the reading surface

   Single column by default; the commentary rail moves alongside at the
   breakpoint in section 17.
   ------------------------------------------------------------------------- */
.specimen-section {
  padding-block: clamp(1.5rem, 1rem + 2vw, 2.5rem) clamp(2.5rem, 2rem + 3vw, 4rem);
}

.specimen {
  display: grid;
  gap: 1.75rem;
  margin: 1.5rem 0 0;
  padding: clamp(1.25rem, 1rem + 2vw, 2.25rem);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper-raised);
  box-shadow: var(--shadow-soft);
}

/* The mushaf line. Generous leading: the marks above and below the letters need
   the room, and a cramped line is the first thing that makes Arabic look wrong. */
/* The upper bound is set by the card and not by taste: the line is right-aligned
   in an RTL block, so anything smaller leaves a wide bay of empty paper down the
   left of the card and the verse stops being the thing the figure is about. */
.mushaf {
  font-family: var(--font-arabic);
  font-size: clamp(1.8rem, 1.2rem + 2.6vw, 3.15rem);
  line-height: 2.05;
  color: var(--ink);
}

/* Tajweed colouring is applied with colour alone -- no padding, border or
   margin -- so the letters keep joining across the span boundary. */
.tj { color: inherit; }

.ayah-mark {
  display: inline-block;
  min-width: 1.6em;
  margin-inline-start: 0.35em;
  padding: 0.05em 0.2em;
  border: 1px solid var(--rule);
  border-radius: 999px;
  font-size: 0.5em;
  line-height: 1.5;
  text-align: center;
  color: var(--accent);
  vertical-align: middle;
}


/* ----------------------------------------------------------------------------
   10. The verse card

   The specimen's left column: one verse drawn the way the study page draws it.

   These rules are a deliberate copy of quran.css's and not an import. base.css
   is served to every page and says in its own header that it is one file read
   top to bottom; pulling the reading stylesheet in to style six elements would
   put the whole study surface on the landing page. The copy is small and the
   cost is understood and stated: if the verse card is restyled over there, this
   figure drifts, and the caption's claim that it is drawn "as the page draws
   it" quietly stops being true. Re-check this section whenever the card moves.
   ------------------------------------------------------------------------- */
.specimen__card {
  /* The gutter the numbered marks sit in. Each mark is absolute inside its own
     part, so the text edge is identical on every row whatever the numeral is. */
  --spec-gutter: clamp(1.95rem, 1.6rem + 1.1vw, 2.45rem);
  min-width: 0;
  padding-inline-start: var(--spec-gutter);
}

/* Section 9's standing note collected on again: the study page's verse number
   grew, so this copy of it grows too, or the caption's claim that the figure
   is drawn as the page draws it stops being true. */
.specimen__num {
  margin: 0 0 var(--space-2);
  font-family: var(--font-sans);
  font-size: 1.55rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
}

.spec-part { position: relative; }
.spec-part + .spec-part { margin-block-start: var(--space-5); }

/* Room above the line for the tooltip, which is taken out of flow so that
   drawing it open does not push the verse down the card. */
.spec-part--mushaf {
  /* Enough for the box and then some: the QCF faces carry the printed mushaf's
     tall metrics, so the marks above an alif reach well past where a Latin
     ascender would stop and a tighter figure has the box resting on them. */
  --spec-tip-room: 4.35rem;
  padding-block-start: var(--spec-tip-room);
}

/* The mushaf line, not the tooltip above it, is what mark 1 points at. */
.spec-part--mushaf > .spec-mark {
  inset-block-start: calc(var(--spec-tip-room) + 0.6rem);
}

/* The word-by-word tooltip, replicated. Anchored to the inline end of the
   block: the line is RTL, so its first word is the rightmost one whether the
   line wraps or not, which makes that edge a stable address where the glyph's
   own box is not. */
.spec-tip {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.spec-tip__box {
  display: grid;
  gap: 0.1rem;
  padding: var(--space-2) var(--space-3);
  border: var(--hair) solid var(--rule-strong);
  border-radius: var(--radius-control);
  background: var(--paper-raised);
  box-shadow: var(--shadow-soft);
  font-family: var(--font-sans);
  text-align: start;
  /* The edge nearest the word carries the accent, as it does in the app, where
     it is what ties the box to the word it is about. */
  border-block-end: var(--emph) solid var(--accent);
}

.spec-tip__gloss {
  font-size: var(--fs-body-sm);
  color: var(--ink);
}

.spec-tip__tl {
  font-size: var(--fs-caption);
  letter-spacing: 0.02em;
  color: var(--ink-faint);
  direction: ltr;
}

/* The hovered word, which is what a still figure has instead of a pointer.
   A copy of quran.css's own hover rule, tint and radius both, so the figure
   shows the state the reading page actually draws. It replaced a recitation
   disc drawn over this word, which went when the app's did.

   Section 9's standing note applies here too: this is a deliberate copy and
   not an import, so re-check it whenever the verse card is restyled. */
.spec-word {
  background: var(--accent-wash);
  border-radius: var(--radius-control);
}

.spec-tr {
  max-width: var(--measure);
  font-size: var(--fs-body-lg);
  line-height: var(--lh-reading);
  color: var(--ink);
}

/* Rizvi's italics are the translator's supplied words. They are content and not
   emphasis, which is why they are toned rather than merely slanted. */
.spec-tr i {
  font-style: italic;
  color: var(--ink-soft);
}

/* The credit sits inside its own translation, so a hidden layer takes its
   attribution with it. No dash prefix: generating one from CSS is still copy. */
.spec-tr__src {
  display: block;
  margin-block-start: var(--space-1);
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  font-style: normal;
  color: var(--ink-faint);
}

.spec-note {
  padding-inline-start: var(--space-4);
  border-inline-start: var(--emph) solid var(--accent-tint);
  font-size: var(--fs-body);
  line-height: var(--lh-reading);
  color: var(--ink-soft);
}

.spec-cites {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Spans, not anchors: on the landing page these illustrate a control rather
   than being one, and a link here would lead somewhere the figure does not
   promise. The 44px height is the app's touch target, kept so the row has the
   proportions a reader will actually meet. */
.spec-cite {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding-inline: var(--space-3);
  border: var(--hair) solid var(--rule);
  border-radius: var(--radius-control);
  background: var(--paper-raised);
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  color: var(--accent-strong);
}

.spec-cite__book {
  width: 15px;
  height: 15px;
  flex: none;
  color: var(--ink-faint);
}

.specimen__caption {
  padding-top: 1.1rem;
  border-top: 1px solid var(--rule);
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--ink-faint);
}


/* ----------------------------------------------------------------------------
   11. The numbered marks

   One ring drawn once and used in both columns, because the mark on the card
   and the mark in the key have to read as the same object rather than as two
   things that happen to share a numeral.

   Hollow, not filled. A filled disc is an emphasis mark, and six of them down
   the side of a verse would shout over the verse; the ring says "this one" and
   nothing more. It is also the treatment the hero's source list already uses,
   and it keeps this figure clear of tints and leading-edge stripes, which mean
   something else in this project.
   ------------------------------------------------------------------------- */
.spec-mark,
.key__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.55rem;
  height: 1.55rem;
  flex: none;
  border: var(--hair) solid var(--accent-strong);
  border-radius: var(--radius-pill);
  background: var(--paper-raised);
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--accent-strong);
}

.spec-mark {
  position: absolute;
  inset-inline-start: calc(var(--spec-gutter) * -1);
  inset-block-start: 0.1rem;
}

/* The tooltip's mark rides beside the box instead, since the box is nowhere
   near the gutter the others share. */
.spec-mark--tip { position: static; }


/* ----------------------------------------------------------------------------
   12. The key

   An <ol>, so the numbering is structural and not painted on. The visible ring
   is the item's own text rather than a list marker, because a marker cannot be
   drawn as the ring on the card; the hidden word "Mark" in front of it is what
   keeps the number from being read out as a bare digit.
   ------------------------------------------------------------------------- */
/* Stacked under the card, the key needs the separation that the vertical rule
   gives it once the two sit side by side. Same rule, turned through a right
   angle; the breakpoint block swaps one for the other. */
.specimen__key {
  min-width: 0;
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--rule);
}

.key {
  display: grid;
  gap: var(--space-4);
  margin-block-start: var(--space-3);
}

.key__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-3);
  align-items: start;
}

.key__body {
  display: grid;
  gap: 0.15rem;
}

.key__name {
  font-weight: 600;
  font-size: 0.98rem;
}

.key__desc {
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--ink-soft);
}


/* ----------------------------------------------------------------------------
   13. The layers

   A counter supplies the numerals, so the markup stays a plain list.
   ------------------------------------------------------------------------- */
.layers-section {
  padding-block: clamp(2.5rem, 2rem + 3vw, 4rem);
  border-top: 1px solid var(--rule);
  background: var(--paper-sunk);
}

.layers {
  display: grid;
  gap: 1rem;
  margin-top: 1.75rem;
  counter-reset: layer;
}

.layer {
  display: grid;
  gap: 0.4rem;
  padding: 1.35rem 1.4rem 1.5rem;
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--paper-raised);
}

.layer::before {
  content: counter(layer, decimal-leading-zero);
  counter-increment: layer;
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: var(--accent);
}

.layer__title { font-size: 1.08rem; }

.layer__body {
  font-size: 0.96rem;
  line-height: 1.7;
  color: var(--ink-soft);
}


/* ----------------------------------------------------------------------------
   14. The reference page

   /how-a-page-is-built. It holds what the landing page used to say a third
   time: the eight layers above, then the controls, at a length the front page
   had no business spending. The specimen stayed on the landing page, because it
   is the evidence for the headline's claim and evidence belongs beside its
   claim; this is the reference, and a reference is what a second page is for.

   Sections alternate --paper and --paper-sunk down the page. That began as the
   only thing telling a reader one subject had ended, back when the page was an
   unbroken run of prose; every section carries a figure now, so the ground is
   the second signal rather than the only one. It is kept because the figures
   are what the alternation now has to serve: see .prose-figure below, where the
   plate under a screenshot flips with the section it stands in.
   ------------------------------------------------------------------------- */
.page-head {
  padding-block: clamp(2.2rem, 1.8rem + 2.5vw, 3.6rem) clamp(1.5rem, 1.2rem + 1.5vw, 2.2rem);
}

.page-head__title {
  margin-top: 0.9rem;
  font-size: clamp(1.9rem, 1.4rem + 1.9vw, 2.6rem);
  line-height: 1.14;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.page-head__dek {
  max-width: var(--measure);
  margin-top: 1rem;
  font-size: 1.14rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

.prose-section {
  padding-block: clamp(2.2rem, 1.8rem + 2.5vw, 3.4rem);
  border-top: 1px solid var(--rule);
}

.prose-section--sunk { background: var(--paper-sunk); }

/* A description list, because that is what these are: a named thing and what it
   does. Rows rather than a two-column grid -- the terms are short and the
   descriptions are three lines, so columns would leave the left one nearly
   empty down the whole page. */
.defs {
  display: grid;
  gap: 1.5rem;
  margin-top: 1.6rem;
  max-width: var(--measure);
}

/* align-content, not the default stretch. Side by side the row is as tall as
   the tallest in its line, and a stretched two-track grid spends that surplus on
   the gap: the shorter entry's description drifts away from the term it belongs
   to, and the pair stops reading as a pair. The slack belongs underneath. */
.defs__row {
  display: grid;
  gap: 0.3rem;
  align-content: start;
}

.defs__term {
  font-family: var(--font-sans);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-strong);
}

.defs__desc {
  margin: 0;
  font-size: 0.99rem;
  line-height: 1.7;
  color: var(--ink-soft);
}

/* The jump list under the page's title.

   A phone's problem before a desktop's: this page is seven sections of prose
   with a screenshot in each, and without this a reader on a narrow screen
   reaches the search section by scrolling past everything else. Anchors and no
   script -- the platform scrolls to a fragment on its own.

   PILLS AND NOT A LIST OF LINKS, and the reason is the thumb. A row of
   underlined words is the lighter treatment and it is the wrong one here: text
   links land near 20px tall, and this control exists for the reader who is
   holding the page in one hand. min-height carries them to 42px, which is the
   same argument .lightbox__close settles with a pointer query.

   They are quieter than .btn--ghost on purpose, at a smaller size and in
   --ink-soft rather than --ink: a ghost button is a peer of "Read Qur'an Now"
   at the foot of this page, and seven of them across the top would outrank the
   one button the page is a detour from. */
.page-nav { margin-top: 1.7rem; }

/* .page-nav__label takes the shared eyebrow rule in section 5 rather than
   restating it here: it is the same label at the same size in the same role. */

.page-nav__list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin-top: 0.7rem;
  padding: 0;
  list-style: none;
}

.page-nav__link {
  display: inline-flex;
  align-items: center;
  min-height: 2.6rem;
  padding-inline: 0.85rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--paper-raised);
  color: var(--ink-soft);
  font-family: var(--font-sans);
  font-size: 0.85rem;
  text-decoration: none;
}

.page-nav__link:hover {
  border-color: var(--accent);
  color: var(--accent-strong);
}

.page-nav__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}


/* A figure inside a prose section.

   THE PLATE FLIPS WITH THE SECTION. .shot mounts a screenshot on --paper-sunk,
   which is chosen in section 20 to separate a near-white capture from the page
   around it. Half the sections here ARE --paper-sunk, and on those the plate
   and the ground are the same colour, so the mount disappears and the picture
   loses its edge. On those it takes --paper instead, which keeps a step in both
   directions: away from the sunk ground beneath it and away from the white
   image inside it. Section 20's instruction to re-measure when a capture
   changes applies to both values.

   No width query. The figure runs the wrap's width and the caption is capped at
   --measure like every other line of prose on the page, so the picture is as
   large as the column allows and the sentence under it stays readable. */
/* margin-inline is the load-bearing half. There is no blanket figure reset in
   this file -- .hero__figure and .feature__figure each zero their own -- so a
   figure that does not is handed the user agent's 40px on both sides, which
   pulls the picture and its caption in from the column everything above them
   sits on. It reads as a deliberate indent and it is a default nobody chose. */
.prose-figure {
  margin: 1.7rem 0 0;
}

.prose-section--sunk .shot,
.layers-section .shot {
  background: var(--paper);
}

/* 56rem, and the number comes from the pictures rather than from taste. The
   panels are shot at 2x from a 1800px window, so the widest of them carries 900
   CSS pixels of content; 56rem is 896 at the root size, which prints them at
   very nearly 1:1. Left at the wrap's 68rem they were blown up about a fifth
   past their own resolution -- soft on a plain screen and softer on a dense one
   -- and each section grew by the height that upscaling added, on a page whose
   brief is to stay short. Re-measure this if the capture width in
   scripts/shoot_figures.py changes. */
.prose-figure .shot {
  max-width: 56rem;
}

.prose-figure__caption {
  max-width: var(--measure);
  margin-top: 0.8rem;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

/* One figure is a control rather than a panel -- the Read/Study pair, 212 CSS
   pixels of it. .shot__img is width:100%, which would blow it up to the wrap's
   width and show a reader a blurred button four times its real size. Capped
   near its natural width instead, so it is printed at the size it is. */
.prose-figure--inline .shot {
  max-width: 17rem;
}


/* The way back to the reading. The page is a detour from the one button that
   matters, so it ends by offering that button again rather than leaving a
   reader to find the masthead. */
.closer {
  padding-block: clamp(2.5rem, 2rem + 3vw, 4rem);
  border-top: 1px solid var(--rule);
  background: var(--paper-sunk);
}

.closer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4) var(--space-5);
}

.closer__line {
  font-size: 1.08rem;
  color: var(--ink-soft);
}



/* ----------------------------------------------------------------------------
   15. The note on access
   ------------------------------------------------------------------------- */
.access {
  padding-block: clamp(3rem, 2.5rem + 3vw, 5rem);
  border-top: 1px solid var(--rule);
}

.access__inner {
  max-width: 40rem;
  text-align: center;
}

.ornament {
  display: block;
  margin: 0 auto 1.1rem;
  color: var(--accent);
}

.access__body {
  margin-top: 1rem;
  font-size: 1.05rem;
  line-height: 1.8;
  color: var(--ink-soft);
  text-wrap: pretty;
}


/* ----------------------------------------------------------------------------
   16. Colophon
   ------------------------------------------------------------------------- */
.colophon {
  border-top: 1px solid var(--rule);
  background: var(--paper-sunk);
}

.colophon__inner {
  display: grid;
  gap: 0.5rem;
  padding-block: 2.25rem 2.5rem;
  max-width: 44rem;
  margin-inline: auto;
}

.colophon__name {
  font-weight: 600;
  font-size: 0.98rem;
}

.colophon__note {
  font-size: 0.9rem;
  line-height: 1.65;
  color: var(--ink-soft);
}

.colophon__meta {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The privacy note sits in the same uppercase line as the preview label, so it
   inherits the tracking rather than restating it. Underlined because it is the
   one link in the colophon and nothing else there is clickable to compare it
   against. */
.colophon__link {
  color: var(--ink-faint);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.colophon__link:hover { color: var(--accent-strong); }

.colophon__sep { margin-inline: var(--space-2); }

/* The Flagbearer portfolio credit: the last row of the footer, and the standard
   placement on every Flagbearer site (centered, hairline above, the quietest
   line on the page).

   The spacing is the colophon's own rhythm rather than a new one. The rows in
   here are 0.5rem apart, so --space-2 of margin on top of that gap puts a full
   --space-4 above the hairline and the same below it, which is the recipe
   Manzar's footer uses for the one rule inside it.

   The mark's colours are Flagbearer brand hexes and not this project's tokens
   on purpose: the roundel is the one element that must render identically on
   every site in the portfolio. */
.colophon__powered {
  margin-top: var(--space-2);
  padding-top: var(--space-4);
  border-top: var(--hair) solid var(--rule);
  display: flex;
  justify-content: center;
}

.powered-by {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2);
  font-family: var(--font-sans);
  /* 12px at the shipped root size, which is the size the credit runs at on
     every Flagbearer site. In rem and not px because this is a reading app and
     a reader who enlarges their default type should carry this line with it.
     The baseline arithmetic below is unaffected: it depends on the mark, whose
     size is fixed in the markup, and never on the text. */
  font-size: 0.75rem;
  color: var(--ink-faint);
  text-decoration: none;
}

/* The lockup is the same device as the flagbearer.org header: the roundel IS
   the F and "lagbearer" completes the word. Two numbers do the work. The 1px
   right margin tucks the l against the disc. The -3px bottom margin drops the
   disc by the distance between the F's foot and the bottom of the circle (the
   stem ends at 39/48 of the viewBox, so 3px on a 16px mark, 18.75%), which
   lands the F's own foot on the text baseline.

   This MUST stay inline layout and must not become a flex container.
   vertical-align: baseline puts a replaced element's bottom MARGIN edge on the
   baseline, so the -3px counts. A flex container synthesises an item's baseline
   from its border box and discards the margin, leaving the disc floating high
   by the whole offset. Measured in headless Chrome, the F's foot against the
   text baseline: inline 0.000px, flex 3.000px. Scale both numbers with the mark
   if the mark ever changes size. */
.powered-by__lockup { white-space: nowrap; }

.powered-by__mark {
  display: inline-block;
  vertical-align: baseline;
  margin: 0 1px -3px 0;
}

.powered-by__name {
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink-soft);
  transition: color var(--dur) var(--ease-calm);
}

.powered-by:hover .powered-by__name,
.powered-by:focus-visible .powered-by__name { color: var(--ink); }


/* ----------------------------------------------------------------------------
   17. Wide layout -- the one breakpoint

   Below 600px everything is a single column, which is the default above. This
   block is the only width query in the file.
   ------------------------------------------------------------------------- */
@media (min-width: 600px) {
  :root { --gutter: 2rem; }

  /* The wordmark keeps its name from here up. Below this it is the mark alone
     and that rule lives outside this query, because section 17 is a MIN-width
     block and the narrow case is the default here. */
  .landing .wordmark__text { position: static; width: auto; height: auto;
                             margin: 0; overflow: visible; clip-path: none; }

  /* The centred formula, and deliberately the same numbers the Qur'an pages
     use: a reader crossing from here to /quran should not see the field jump
     width or the wordmark change place. max-content floors on the flanks
     rather than 0 -- with minmax(0, 1fr) the tracks shrink below their
     contents and "Quran Study" wraps onto two lines, taking the row from 76px
     to 88px, which is the measurement recorded beside the Qur'an copy. */
  .landing .masthead__inner:has(.qsearch) {
    grid-template-columns:
      minmax(max-content, 1fr) minmax(0, 24rem) minmax(max-content, 1fr);
    justify-items: center;
  }

  .landing .masthead__inner > .wordmark { justify-self: start; }
  .landing .masthead__inner > .masthead__actions { justify-self: end; }

  /* The verse and its key side by side. Below this the key stacks under the
     card, where the numbers still carry the pairing without the eye having to
     travel: the ring is the same ring wherever the two columns end up. */
  .specimen {
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: 2rem;
  }

  .specimen__key {
    padding-block-start: 0;
    border-block-start: 0;
    padding-inline-start: 2rem;
    border-inline-start: 1px solid var(--rule);
  }

  .specimen__caption { grid-column: 1 / -1; }

  .layers { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.1rem; }

  /* Two columns, like the layers above them. Single-column definition rows are
     capped at --measure, which on a wide screen leaves the right half of three
     consecutive sections empty while the grid above fills it -- and the eye
     reads that as the page having lost its nerve halfway down. The cap comes
     off because each column is now narrower than the measure anyway. */
  .defs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.7rem 2rem;
    max-width: none;
  }
}


/* ----------------------------------------------------------------------------
   18. Motion

   The page animates almost nothing; what little there is stops on request.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}


/* ----------------------------------------------------------------------------
   19. The mushaf glyph specimen

   The Uthmani mushaf is not set from a normal Arabic font. The King Fahd
   Complex digitised Uthman Taha's Madani mushaf as one font per printed page,
   addressed by page-relative private-use codepoints. Verse 96:1 sits on printed
   page 597, so p597.woff2 is the only face this page needs out of the 604.

   The file is stored byte-for-byte as published. The licence permits
   distribution but forbids subsetting, re-compression or any modification, so
   it is not optimised and must not be.

   font-display: block is deliberate, not an oversight. A glyph code is
   meaningless in any other font, so a fallback face would paint garbage. The
   line stays blank until the real face arrives, which is the same honest reveal
   the reading app uses.

   Tajweed colour lives inside this font, as COLR layers over CPAL palette 0.
   CSS `color` cannot reach it. That is why the key beside the specimen names
   the rules in words and carries no colour dots: a dot painted from a --tj-*
   token would assert a rule-to-colour mapping this font does not necessarily
   use. The names used to sit in a legend of their own under the line; they are
   in the key's first entry now, so the figure has one legend rather than two.
   ------------------------------------------------------------------------- */
@font-face {
  font-family: "qcf4-p597";
  src: url("../fonts/qcf/v4/p597.woff2") format("woff2");
  font-display: block;
}

.mushaf--glyph {
  font-family: "qcf4-p597";
  /* 1.8, not the 2.05 the typeset line uses: the QCF faces carry the printed
     mushaf's own tall metrics, so the usual correction doubles up. */
  line-height: 1.8;
}

/* Every glyph span is aria-hidden and shadowed by real Uthmani text in a
   .visually-hidden sibling, so screen readers and select-all copy get the verse
   rather than private-use codepoints. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* ----------------------------------------------------------------------------
   20. The split view screenshot

   Not a mock-up, and no longer a borrowed one: this application's own study
   page, captured whole from the masthead down, so the claim in the headline is
   evidence rather than assertion. It sits in the hero at roughly a third of its
   native width and is clickable through to the full 2308px capture, which is
   where the detail is.
   ------------------------------------------------------------------------- */
/* Both figures on the landing page wear this: one caption treatment, one rule,
   so a change to how a picture is captioned cannot reach one of them only. */
.hero__caption,
.feature__caption {
  margin-block-start: 0.8rem;
  font-size: 0.8rem;
  line-height: 1.55;
  color: var(--ink-faint);
}

/* Mounted like a plate, on --paper-sunk rather than straight onto --paper.

   The reason is measured, not decorative, and the measurement changed when the
   capture did. This one starts at its own masthead, so its border ring averages
   luminance 0.929 where the shot it replaced averaged 0.870. Against --paper
   (#faf7f2, luminance 0.933) that is a surround four thousandths brighter than
   the image edge: the picture would have no boundary at all, and the ring below
   would be doing the whole job of saying where it ends. --paper-sunk is 0.844,
   0.085 below the edge, which separates the two without darkening either.

   The plate therefore survives its original argument. It was chosen to stop a
   darker capture reading as a dull panel through simultaneous contrast; it is
   kept because a near-white one needs an edge. Re-measure if this is replaced
   again: a capture that lands back near 0.87 wants the first reasoning, and one
   that lands here wants this one. */
.shot {
  display: block;
  position: relative;
  padding: 0.7rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper-sunk);
  box-shadow: var(--shadow-soft);
}

.shot__img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) - 7px);
}

/* The one filled accent control in this figure: it says the picture is a door,
   not a decoration. */
.shot__hint {
  position: absolute;
  inset-block-end: 1.15rem;
  inset-inline-end: 1.15rem;
  padding: 0.28rem 0.58rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--paper-raised);
  font-family: var(--font-sans);
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.shot:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}


/* ----------------------------------------------------------------------------
   21. The enlarged view

   A native <dialog>, so focus trapping and Escape-to-close come from the
   platform. static/js/lightbox.js opens it; without that script the trigger is
   still a plain link to the same image.
   ------------------------------------------------------------------------- */
.lightbox {
  width: min(96vw, 2304px);
  max-width: 96vw;
  max-height: 94vh;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  overflow: visible;
}

.lightbox::backdrop {
  background: rgba(22, 19, 15, 0.82);
}

.lightbox__scroll {
  max-height: 94vh;
  border-radius: var(--radius);
  overflow: auto;
  overscroll-behavior: contain;
}

.lightbox__img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 94vh;
  object-fit: contain;
  border-radius: var(--radius);
  background: var(--paper-raised);
}

/* THE ENLARGEMENT THAT ACTUALLY ENLARGES, and it only exists on a touch screen.
   Fit-to-screen is the right answer under a cursor: the dialog is 96vw, a
   desktop window is wider than any capture here, and the picture lands bigger
   than it was on the page. On a phone that same rule enlarges a 350px figure to
   374px, which is not an enlargement -- the reader pressed a button labelled
   Enlarge and got back what they were already looking at.

   So on a coarse pointer the image is printed at its natural size inside a
   scroll box and the reader pans it. The captures are 2x, so natural size is
   twice the CSS pixels the panel occupied on the desktop it was shot on, and
   the smallest label in the hadith grid comes back to a readable size.

   Pointer and not width, which is the axis this file already allows itself for
   .lightbox__close two rules down: the one-breakpoint rule governs LAYOUT
   widths, and this is about what is holding the device. It is also the truer
   test -- a small window under a mouse can still fit the picture and should not
   be made to pan it.

   The scroll box and not the dialog, so that .lightbox__close stays pinned to
   the dialog's own corner rather than scrolling off the top of a panned image. */
@media (pointer: coarse) {
  .lightbox__img {
    width: auto;
    max-width: none;
    max-height: none;
  }
}

.lightbox__close {
  position: absolute;
  inset-block-start: 0.6rem;
  inset-inline-end: 0.6rem;
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding: 0 0.6rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--paper-raised);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
}

.lightbox__close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* 44px under a thumb, the old size under a cursor. Same inversion as the
   reading page's controls; a pointer query is not a width breakpoint, so the
   one-breakpoint rule this file defends is untouched. */
@media (pointer: fine) {
  .lightbox__close { min-width: 2.1rem; min-height: 2.1rem; }
}


/* ----------------------------------------------------------------------------
   22. The Dictionary & Grammar feature

   Why a component that appears mid-page is styled at the end of a file that
   claims to run in page order: its figure is section 20's plate, reused rather
   than restyled, and nothing here may be overridden by the breakpoint block,
   so it has to sit below section 17. Sections 20 and 21 are down here for the
   same reason -- the hero's own screenshot is styled below the breakpoint too,
   not beside the hero.

   ONE COLUMN, FIGURE IN THE MIDDLE. Lead, then the picture at the full content
   width, then the highlights beneath it. This replaced a two-column
   copy-beside-figure arrangement on 2026-08-22, and the reason is the picture
   rather than the prose: the figure was a portrait crop of the pane alone and
   is now the whole split, and a landscape frame in a half-width column renders
   each of its halves at roughly 250px -- narrower than the crop it replaced,
   which would have defeated the point of widening it. At full width the halves
   land near 540px each and the marked word in the verse is legible beside its
   entry in the panel.

   Section 20 asks for the plate to be re-measured whenever a capture changes,
   so: this one's border ring averages luminance 0.953, against --paper at 0.933
   and --paper-sunk at 0.844. It is BRIGHTER than the page, so on --paper it
   would have no boundary at all and the ring below would be doing the whole job
   of saying where the picture ends. The sunk plate gives it 0.109 of
   separation. Section 20's second reasoning therefore holds for both figures,
   which is why they share .shot rather than each carrying a mount.
   ------------------------------------------------------------------------- */
.feature {
  padding-block: clamp(2.5rem, 2rem + 3vw, 4rem);
  border-top: 1px solid var(--rule);
}

.feature__lead {
  max-width: var(--measure);
}

/* One step below the hero's standfirst, because it answers an h2 and not the
   h1. Full --ink all the same: it is the sentence the section is about. */
.feature__dek {
  margin-top: 0.9rem;
  font-size: clamp(1.05rem, 1rem + 0.3vw, 1.18rem);
  line-height: 1.55;
  color: var(--ink);
  text-wrap: pretty;
}

.feature__figure {
  margin: clamp(1.5rem, 1rem + 2vw, 2.25rem) 0 0;
}

/* The picture is full width; its caption is not. Section 20's caption never
   needed a cap because it sits in the hero's narrow column, but here the same
   0.8rem type would run the whole 68rem wrap -- about 180 characters a line,
   two and a half times the measure this page sets for body text. The figure
   keeps the width; the sentence under it does not. */
.feature__caption {
  max-width: var(--measure);
}

/* Name and sentence per row, which is the specimen key's shape one section up,
   and the hero list's hollow ring as the marker. Two existing idioms rather
   than a third: the page already says "list" one way and "name over
   description" another, and this block is both at once.

   TWO columns on a wide screen, one when there is no room, decided by auto-fit
   against an intrinsic minimum rather than by a width query -- so section 17
   remains the only breakpoint in this file.

   24rem is the floor, and the number is arithmetic rather than taste. The wrap
   caps at 68rem, so the widest this grid is ever measured against is 1088px; a
   third track would need 3 x 384 + 2 x 40 of gap = 1232px, which never arrives.
   19rem was tried first and gives THREE columns at any window past ~1200,
   which leaves the fourth highlight orphaned on a row of its own -- four items
   want two columns or one, never three.

   The min() is load-bearing and not a flourish: a bare minmax(24rem, 1fr) is a
   FLOOR the track keeps even when its container is narrower, so at a 320px
   viewport a 280px wrap holds an oversized track and the page scrolls
   sideways. min(24rem, 100%) lets the track give way once there is less than
   24rem to have. Caught by the width sweep, which is the second time this
   section has been saved by measuring 320 rather than reasoning about it. */
.feature__points {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(24rem, 100%), 1fr));
  gap: var(--space-4) clamp(1.5rem, 1rem + 2vw, 2.5rem);
  margin: clamp(1.5rem, 1rem + 2vw, 2.25rem) 0 0;
  padding: 0;
  list-style: none;
}

.feature__points li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-3);
  align-items: start;
}

/* The name and the sentence share ONE grid item, in a wrapper, which is what
   .key__item does and is not a stylistic echo: with three items in a
   two-column grid the third wraps onto a second row and lands in the marker's
   `auto` column, which then sizes to the longest description and pushes the
   page 65px wider than the viewport at 320. Caught by the width sweep, not by
   reading the rule. */
.feature__point-body {
  min-width: 0;
}

/* A real grid column rather than an absolutely positioned marker, so the ring
   cannot land on top of the text at any measure. It is centred on the NAME's
   line box and the arithmetic is written out rather than rounded to a nudge:
   the name's own line-height is declared below precisely so this holds. */
.feature__points li::before {
  content: "";
  width: 0.44rem;
  height: 0.44rem;
  margin-block-start: calc((0.98rem * 1.45 - 0.44rem) / 2);
  border: 1px solid var(--accent-strong);
  border-radius: 50%;
}

/* Forced colours keeps borders and forces their colour, so the ring survives.
   Stated for the same reason section 8 states it: a background here would fill
   the counter and turn the ring into the solid dot it is meant not to be. */
@media (forced-colors: active) {
  .feature__points li::before {
    background: transparent;
    border-color: CanvasText;
  }
}

.feature__point-name {
  display: block;
  font-size: 0.98rem;
  line-height: 1.45;
  font-weight: 600;
  color: var(--ink);
}

.feature__point-desc {
  display: block;
  margin-block-start: 0.1rem;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

/* The provenance. Set off by a rule rather than by size alone, because it is a
   different kind of statement from the four above it -- not a fifth thing the
   panel does, but the rule the four were built under. */
.feature__note {
  max-width: var(--measure);
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--rule);
  font-size: 0.88rem;
  line-height: 1.65;
  color: var(--ink-soft);
}

/* ----------------------------------------------------------------------------
   23. The search bar

   Moved here whole from quran.css section 9 on 2026-08-23: the universal bar
   stands in the landing hero as well as the /quran masthead, and the landing
   page does not load quran.css. The masthead grid the bar sits in on the
   Qur'an pages stays in quran.css beside the other masthead grids. Ported
   from Manzar originally; the masthead measurements are recorded there.
   ------------------------------------------------------------------------- */

.qsearch {
  position: relative;          /* the panel drops from here */
  display: flex;
  align-items: center;
  inline-size: 100%;
  min-inline-size: 0;
}

.qsearch__icon {
  position: absolute;
  inset-inline-start: 0.85rem;
  display: inline-flex;
  color: var(--ink-faint);
  pointer-events: none;        /* the click belongs to the field behind it */
}

/* 44px to match the Display button exactly, so the two read as one family and
   so the row's height is unchanged. */
.qsearch__input {
  inline-size: 100%;
  min-inline-size: 0;
  block-size: 44px;
  padding-inline: 2.4rem 0.9rem;
  border: var(--hair) solid var(--rule-strong);
  border-radius: var(--radius-pill);
  background: var(--paper-raised);
  font-family: var(--font-sans);
  /* 1rem, and NOT the --fs-body-sm the rest of this control set uses. iOS
     Safari zooms the whole page in on any field it focuses that is set under
     16px, and it does not zoom back out when the field is left: the reader is
     left on a magnified page with the surah running off the side, having done
     nothing but tap the search box. 16px is the threshold, so this is the one
     place in the stylesheet where the type scale gives way to the platform. */
  font-size: 1rem;
  color: var(--ink);
  /* The BOX stays in the chrome's direction while the TEXT runs in its own.

     dir="auto" on the input is right for the text and wrong for everything
     around it: typing Arabic flips the element's direction to rtl, and
     padding-inline resolves against the ELEMENT, so the 2.4rem cut for the
     magnifier moved to the right and the 3.25rem cut for the keyboard mark
     moved to the left -- putting the typed word underneath the button and
     leaving 52px of nothing beside a 16px magnifier. Measured 2026-08-25 with
     سلمون in the field: direction rtl, padding 52px left and 38.4px right.

     The icon and the button are both anchored with inset-inline against the
     FORM, which has no dir and is therefore the chrome's ltr. Pinning the
     input to the same direction puts all three back on one axis, and
     plaintext keeps what dir="auto" was actually wanted for: the paragraph's
     own direction is still detected per content, so Arabic still orders and
     aligns right. The attribute stays in the markup as the no-CSS answer. */
  direction: ltr;
  unicode-bidi: plaintext;
  outline: none;
  transition: border-color var(--dur) var(--ease-calm),
              box-shadow var(--dur) var(--ease-calm);
}

/* Room for the keyboard mark, and only when there is a mark to make room for.
   The button ships hidden and search.js unhides it, so the test is :not([hidden])
   rather than the element's presence: with script off nothing is drawn there and
   the field keeps the whole 0.9rem.

   3rem is the button's 44px plus 4. The 4 is the clearance from the BUTTON's
   edge; the clearance from the mark inside it is 16.5px, because the 19px mark
   is centred in the 44. It was 3.25rem for one sweep, and the 4px came back
   because at 320px -- where the field is the whole row and the only costs left
   are its two paddings -- the sample fitted with 0.0px to spare, and a floor
   measured at exactly zero is not a floor. */
.qsearch:has(.qsearch__keytoggle:not([hidden])) .qsearch__input {
  padding-inline-end: 3rem;
}

.qsearch__input::placeholder { color: var(--ink-faint); }

.qsearch__input:hover { border-color: var(--accent); }

.qsearch__input:focus-visible,
.qsearch__input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 var(--focus-width) var(--accent-tint);
}

/* Chrome draws its own clear button on type=search. It sits where the panel's
   scrollbar wants to be and is not styleable, so it goes. Escape clears the
   field, which is the behaviour it duplicates. */
.qsearch__input::-webkit-search-cancel-button { display: none; }

/* --- the dropdown -------------------------------------------------------- */

/* One absolutely-positioned column holds the Arabic keyboard and the list,
   keys first -- the Dictionary & Grammar panel's own lesson, learned when the
   two hung from the same anchor and the keyboard covered the results it was
   being used to find. Keys first because their height is fixed and the list's
   changes with every keystroke, so the keys never move under the finger
   tapping them. The cap stays ON THE LIST, never on the pair: opening the
   keyboard must not silently halve the visible matches. The column's own
   ceiling is the short-screen backstop, and what gives there is always the
   list, which scrolls, never the keyboard, which cannot. */
.qsearch__under {
  position: absolute;
  inset-block-start: calc(100% + var(--space-2));
  inset-inline-start: 50%;
  transform: translateX(-50%);
  z-index: 96;
  /* 100cqi, the masthead's own width, and not 100vw. This column hangs off a
     field that stands in half the page once a panel is open, so a window-wide
     cap let its leading edge fall off the document -- 19px at a 992px window
     with the seam at its wall. The same measurement .qs-panel makes with
     --qs-pagew; cqi is the shorter way to ask it from inside the container. */
  inline-size: min(30rem, calc(100cqi - 2 * var(--gutter)));
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-block-size: calc(100vh - 9rem);
  max-block-size: calc(100dvh - 9rem);
}

.qsearch__panel {
  min-block-size: 0;
  /* See the note at .contents__list. This is the panel that needs it most: it
     drops from a focused text field, so on a phone the keyboard is up while it
     is open and the space it is sizing itself against is at its smallest. */
  max-block-size: min(26rem, calc(100vh - 9rem));
  max-block-size: min(26rem, calc(100dvh - 9rem));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-1);
  border: var(--hair) solid var(--rule-strong);
  border-radius: var(--radius);
  background: var(--paper-raised);
  box-shadow: var(--shadow-soft);
}

/* The keys grid sets display, which outranks the user agent's [hidden] rule;
   the panel keeps the same guard so neither can be left permanently visible. */
.qsearch__panel[hidden] { display: none; }

.qsearch__row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-control);
  font-family: var(--font-sans);
  text-decoration: none;
  color: var(--ink);
}

/* One highlight for pointer and keyboard both, so Enter always opens the row
   under the cursor.

   A solid fill: the whole row in the accent, its text flipped to read on it.
   Not a tint, and not a bar down the leading edge -- house rule, and the pale
   wash plus accent stripe this replaced is the exact shape that rule names. A
   confidently filled row is the plain list-selection idiom instead, and the
   reason it works is area rather than contrast: the tint measured 1.17:1
   against the panel in light and 1.26:1 in dark, a wash rather than a state,
   while this is 10.1:1 across the row.

   `--paper` is the right text colour in BOTH themes without a second token,
   which is a property of the palette rather than a coincidence: the accent is
   dark on light paper and light on dark paper, so paper is always its opposite.
   9.5:1 in light, 10.8:1 in dark. */
.qsearch__row.is-active {
  background: var(--accent-strong);
  color: var(--paper);
}

/* Every child that sets a colour of its own has to be told. The last selector
   matters most: the "see all matches" title is accent-strong, which on an
   accent-strong fill is the fill, i.e. invisible. */
.qsearch__row.is-active .qsearch__num,
.qsearch__row.is-active .qsearch__title,
.qsearch__row.is-active .qsearch__meaning,
.qsearch__row.is-active .qsearch__ar {
  color: var(--paper);
}

/* The secondary text keeps its hierarchy by stepping back from the fill rather
   than by changing hue. Still 6.3:1 in both themes. */
.qsearch__row.is-active .qsearch__num,
.qsearch__row.is-active .qsearch__meaning,
.qsearch__row.is-active .qsearch__ar {
  opacity: 0.78;
}

/* Author colours are discarded under forced colours, so the state is restated
   in system terms. forced-color-adjust is what allows the fill at all there. */
@media (forced-colors: active) {
  .qsearch__row.is-active {
    forced-color-adjust: none;
    background: Highlight;
    color: HighlightText;
  }
  .qsearch__row.is-active .qsearch__num,
  .qsearch__row.is-active .qsearch__title,
  .qsearch__row.is-active .qsearch__meaning,
  .qsearch__row.is-active .qsearch__ar {
    color: HighlightText;
    opacity: 1;
  }
}

.qsearch__num {
  flex: none;
  min-inline-size: 1.75rem;
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  text-align: end;
}

.qsearch__main {
  flex: 1 1 auto;
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
}

.qsearch__title {
  font-size: var(--fs-body-sm);
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.qsearch__meaning {
  font-size: var(--fs-caption);
  color: var(--ink-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.qsearch__ar {
  flex: none;
  font-family: "Amiri Quran", var(--font-arabic);
  font-size: 1.05rem;
  line-height: 1.4;
  color: var(--ink-soft);
}

.qsearch__all {
  margin-block-start: var(--space-1);
  border-block-start: var(--hair) solid var(--rule-soft);
  border-radius: 0 0 var(--radius-control) var(--radius-control);
}

.qsearch__all .qsearch__title { color: var(--accent-strong); font-weight: 600; }

.qsearch__empty {
  margin: 0;
  padding: var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--fs-body-sm);
  color: var(--ink-faint);
}

/* --- the Arabic keyboard, universal mode only ----------------------------- */

/* Ships hidden and is unhidden by search.js: it can do nothing without
   script, which is the Display button's own rule.

   INSIDE the field, at the trailing end, where the magnifier already stands at
   the leading one. It used to be a 116px pill beside the box, flex: none and
   nowrapped, taking its width out of a track capped at 24rem -- and the input
   beside it has min-inline-size: 0, so the input paid the whole difference.
   Measured 2026-08-25: the placeholder needs 188px and had 205px at a 1280
   window with nothing open, 88px at 1400 with a panel, and NOTHING at all
   between 992 and 1114, where the pill overhung the field and sat on top of
   the All surahs link. Out of flow, it costs the track nothing at any width,
   which is a fix with no breakpoint in it.

   Absolute against .qsearch, which is already position: relative. 44px wide
   and the field's full height, so the hit area keeps its floor while the mark
   inside it stays 19px. inset-block rather than a height, so the 40px field
   below 40rem is followed without a second rule.

   Accent text because it is pressable; solid accent on the field's own end cap
   while the keys are out, which is the treatment it already had as a pill and
   the one every active row here uses. The word it carried moves to the
   accessible name and the tooltip -- see the template for why that is
   affordable here and is NOT affordable in the word panel's copy. */
.qsearch__keytoggle {
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px;
  /* Trailing room for the key inside the cap, NOT an inset on the cap itself.
     The cap's own edge stays flush with the field's, because when the keyboard
     is open the cap fills with accent and its two end corners are rounded to
     continue the pill -- inset it and that fill stops short of the edge it is
     meant to finish. So the box moves and the target does not: still 44px,
     still the full height, which is what the door's own size pin measures. */
  padding: 0 10px 0 0;
  border: 0;
  border-start-end-radius: var(--radius-pill);
  border-end-end-radius: var(--radius-pill);
  background: none;
  color: var(--ink-faint);
  cursor: pointer;
}

/* display is inline-flex above, so the attribute needs saying again. */
.qsearch__keytoggle[hidden] { display: none; }

/* The mark is three letters, not a drawing, so it is sized like type. The
   line-height is flattened because Amiri's line box carries the descender
   room a naskh face needs and would push the letters off the cap's centre --
   the same correction the panel's Arabic pills make.

   The box around them is a KEY, and it is deliberately the same treatment
   .qsearch__key wears below: a hairline and a rounded corner. The mark is a
   miniature of the thing it opens, which is the shortest way to say
   "keyboard" without drawing one -- the drawing is what this replaced.

   currentColor, not --rule-soft, though the keys themselves use the token:
   the cap inverts to an accent fill when the keyboard is open, and a soft
   rule would vanish into it. The border has to travel with the text.

   Not --radius-control (10px). At a cap this size that reads as a pill, and
   a pill is a tag rather than a key; 4px is the corner a key has. The one
   place in this file a radius is written rather than taken from a token, and
   this is why. */
.qsearch__keymark {
  font-family: var(--font-arabic);
  font-size: 0.9rem;
  line-height: 1;
  border: var(--hair) solid currentColor;
  border-radius: 4px;
  /* Naskh sits high in its box, so the cap needs more room under the letters
     than over them or the glyphs ride the top border. */
  padding: 2px 4px 4px;
}

.qsearch__keytoggle:hover { color: var(--accent-strong); }

.qsearch__keytoggle[aria-expanded="true"] {
  background: var(--accent-strong);
  color: var(--paper);
}

/* Drawn INSIDE the cap. A positive offset would ring the field's own border
   from the outside and read as the field being focused, which it is not. */
.qsearch__keytoggle:focus-visible {
  outline: var(--focus-width) solid var(--accent-strong);
  outline-offset: calc(-1 * (var(--focus-width) + var(--hair)));
}

/* Author backgrounds are discarded under forced colours, so the open state
   has to restate itself in system colours or it vanishes. */
@media (forced-colors: active) {
  .qsearch__keytoggle[aria-expanded="true"] {
    background: Highlight;
    color: HighlightText;
    forced-color-adjust: none;
  }
}

/* The key grid is its own card above the list. auto-fit, so the row count is
   the width's decision rather than a measured one, and the two wide keys read
   as a bottom rank wherever the wrap falls. */
.qsearch__keys {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(2.5rem, 1fr));
  gap: 3px;
  padding: var(--space-1);
  border: var(--hair) solid var(--rule-strong);
  border-radius: var(--radius);
  background: var(--paper-raised);
  box-shadow: var(--shadow-soft);
}

.qsearch__keys[hidden] { display: none; }

.qsearch__key {
  min-block-size: 40px;
  border: var(--hair) solid var(--rule-soft);
  border-radius: var(--radius-control);
  background: var(--paper);
  font-family: var(--font-arabic);
  font-size: 1.15rem;
  color: var(--ink);
  cursor: pointer;
}

.qsearch__key:hover { border-color: var(--accent); color: var(--accent-strong); }

/* The grid runs right to left because its letters do; these two keys are
   labelled with English words, so they turn their own direction back. Without
   it the label is still spelled correctly -- bidi reorders runs, not letters
   -- but it sits against the wrong edge of a key twice as wide as the rest,
   which reads as a mistake even to someone who cannot name it. */
.qsearch__key--wide {
  grid-column: span 2;
  direction: ltr;
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
}

/* --- the grouped dropdown, universal mode only ---------------------------- */

/* A group's heading is a label, never an option: it does not enter the walked
   rows and carries no role of its own -- the group's aria-labelledby points
   at it. */
.qsearch__grouphead {
  margin: 0;
  padding: var(--space-1) var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.qsearch__group + .qsearch__group {
  margin-block-start: var(--space-1);
  border-block-start: var(--hair) solid var(--rule-soft);
  padding-block-start: var(--space-1);
}

/* A dictionary row: the Arabic is the answer, so it leads, in the reading
   face; the label and the count explain it in the caption voice the surah
   rows already use. */
.qsearch__word {
  flex: none;
  min-inline-size: 3.2rem;
  font-family: "Amiri Quran", var(--font-arabic);
  font-size: 1.15rem;
  line-height: 1.6;
  color: var(--ink);
}

.qsearch__row.is-active .qsearch__word { color: var(--paper); }

@media (forced-colors: active) {
  .qsearch__row.is-active .qsearch__word { color: HighlightText; }
}

/* The line that holds the dictionary group's place while its fetch is still
   in flight. Not an option; never walked. */
.qsearch__pending {
  margin: 0;
  padding: var(--space-1) var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  color: var(--ink-faint);
}

/* The hero variant was here until 2026-08-24: a 52px field at 1.0625rem in a
   34rem wrapper, sized to stand as the landing page's front door in the middle
   of the copy. It went with the field, which is in the masthead now and takes
   the masthead's 44px like every other control in that row. The modifier is
   gone from _universal_search.html too; nothing sets search_variant to "hero"
   any more. Recorded rather than silently deleted because the sizes are the
   only trace of what the hero arrangement measured. */


/* ----------------------------------------------------------------------------
   24. The masthead's ladder

   LAST IN THE FILE ON PURPOSE. Every rung here is the container twin of an
   @media rung further up, and a twin only tightens its original when the bar
   is narrower than the window -- which is to say when a panel is open. Same
   specificity, later position, so the twin wins where both apply and the media
   rung is untouched for any engine that cannot read this block.

   The bar gives way by REMOVING a named thing at each rung, never by letting a
   box compress. That is the rule the word panel's two ladders arrived at: a
   layout decided by measuring overflow has to be built so the thing that does
   not fit overflows rather than shrinks, or nothing can see what went. The one
   box here that used to give way silently was .qsearch__input, which has
   min-inline-size: 0 and no floor and so paid for everything else.

   THE ARITHMETIC, measured in Chrome on 2026-08-25 and not derived. The
   placeholder "Try kahf, or Arabic like سلم" renders at 187.6px in the system
   sans at the 16px this field is locked to. Around it the field spends 38.4px
   on the magnifier's cut, 48px on the keyboard mark's, and 2px of border, so a
   field that shows its whole sample is 276px wide. The flanks are the wordmark
   at 143px named and 22px as its mark alone, the surah page's actions at
   178px, the landing page's at 114px, and two 24px gaps -- 24px only from a
   600px VIEWPORT up, because both the gutter and the gap step below that.
   ------------------------------------------------------------------------- */

/* RUNG: the name sheds against what actually SHARES ITS ROW, and nothing else.

   SUPERSEDES the single 46rem rung this section shipped with on 2026-08-25.
   That number was measured on the surah page, whose flanks are the widest of
   the three, and then applied to all of them -- so it took the name off the
   index at 700px, where the field had 566px and wanted 167 of them, and off a
   stacked surah page, where there is no field on that row to compete with at
   all. The owner said the words were gone from the site and they were right:
   one number cannot answer three different rows. This is the same mistake the
   word panel's header made and recorded on 2026-08-23 -- ONE LADDER OVER TWO
   HALVES WAS THE WHITE SPACE -- so each row sheds on its own overrun now.

   The landing page's own rung is its 600px restoration below, moved down to
   21rem: the only thing beside the name on a stacked row one is the CTA, and
   143 + 24 + 114 needs 281px of inner, which is a 321px bar. Above the
   restack the row is never narrower than 46rem, where the name fits outright.
   The Qur'an pages' rungs are in quran.css beside the rows they answer.

   Hidden the accessible way and never with display: none, for the reason
   quran.css records where it does the same: the span is the home link's only
   text and the mark beside it is aria-hidden, so removing it from the tree
   leaves the link with no name at all. */
@container masthead (min-width: 21rem) {
  .landing .wordmark__text {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip-path: none;
  }
}

/* RUNG: the row stops holding three things, so the field takes one of its own.

   The LANDING page joins the restack the Qur'an pages have had since
   2026-08-20: it had stayed a single row from 320px down, where an
   incompressible mark, keyboard pill and filled CTA left the field 0px of
   content at 320 and 3.9px at 390.

   46rem AND NOT 40, which is where it first shipped. Between the two the row
   can hold the name, the field and the CTA only by putting them 24px apart and
   cutting the sample -- at 660 the field gets 291px against the 276 it needs
   and the CTA sits one gap away, which the owner read as too close, and it was.
   Stacked, that width has room for all of it: row one carries the name and the
   CTA at opposite ends of 596px, and the field gets the whole of row two.
   Height is what buys it, one 48px row on a window wide enough to spare it,
   which is the opposite trade from the phone and is right for the opposite
   reason.

   :has(.qsearch) so the two-track fallback below stays intact: with the
   universal search dark the landing page renders no bar at all, and a grid
   with a search area and nothing to put in it strands the CTA mid-row. */
@container masthead (max-width: 45.999rem) {
  .landing .masthead__inner:has(.qsearch) {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "brand  actions"
      "search search";
    row-gap: var(--space-3);
  }

  .landing .masthead__inner > .wordmark { grid-area: brand; justify-self: start; }
  .landing .masthead__inner > .masthead__actions { grid-area: actions; justify-self: end; }
  .landing .qsearch { grid-area: search; }

  /* No margin on this row: the field is alone on its own line here, so the
     horizontal separation the single-row layout has to buy is free.

     THE VERTICAL SEPARATION IS NOT FREE, and it was 4px. var(--space-1) is the
     gap this restack shipped with, and on a phone it put the field hard under
     the filled CTA -- 4px against the 16px of padding the masthead keeps above
     and below the pair, so the two rows read as one crushed block inside a
     frame three times their own spacing. The owner, on a phone: "i dont see
     the padding between the search and the top line".

     12px and not 16. The gap stays SHORTER than the 16px frame on purpose:
     equal to it and the two rows read as two separate bars that happen to be
     adjacent, whereas under it they read as one masthead with two lines in it,
     which is what they are. Costs the phone 8px of header, measured 121px to
     129px on the front page at 390. */
  .landing .masthead__inner > .masthead__actions { margin-inline-start: 0; }

  /* 40px rather than 44, the number the Qur'an pages already drop to here: the
     field is no longer beside the Display button so it no longer has to match
     its height, and on a short phone the header is the scarcest thing there
     is. The keyboard mark is inset-block: 0, so it follows without a rule. */
  .qsearch__input { block-size: 40px; }
}

