/* ==========================================================================
   imanulhuq.com — shared stylesheet          v3.3 · 17 Aug 2026  (brand identity: navy / teal / gold / cream, IH script lockup)
   (If your page doesn't look like the latest build, check this line first.)
   Extends the theme from the teaching-philosophy page across the whole site.
   Edit colours and type in the :root block below; nothing else needs touching.
   ========================================================================== */

:root{
  /* ---- BRAND PALETTE -----------------------------------------------------
     Navy / teal / gold / cream. Roughly 70% cream and neutrals, 20% navy and
     teal, 10% gold — gold stays an accent, never a surface.
     --------------------------------------------------------------------- */
  --brand-navy:#071B2E;
  --brand-teal:#0B5558;
  --brand-gold:#D69A28;
  --brand-cream:#FAF7F1;
  --brand-ivory:#FFF9ED;
  --text-primary:#40464B;
  --text-secondary:#686E71;   /* the given #747A7D measures 4.07:1 on cream —
                                 short of AA for the dates, captions and
                                 publication metadata it is used on. Darkened
                                 the minimum needed: this is 4.84:1. */

  /* Values the palette does not name, derived to sit inside it ------------ */
  --brand-gold-deep:#946611;  /* Gold at 2.31:1 on cream is decoration only.
                                 The eyebrows, dates and active nav markers are
                                 14px text and need 4.5:1, so text-gold is the
                                 same hue darkened to 4.71:1. Pure gold stays
                                 available as --gold for rules and hairlines,
                                 where contrast rules do not apply. */
  --brand-alert:#9A3412;      /* form errors. Gold cannot carry a warning and
                                 teal does not read as one. 6.83:1 on cream. */

  /* ---- SEMANTIC TOKENS (light) ------------------------------------------
     Everything in the stylesheet references these, so the two themes below
     are the only place a colour is ever chosen.
     --------------------------------------------------------------------- */
  --ground:var(--brand-cream);
  --panel:var(--brand-ivory);
  --ink:var(--text-primary);
  --heading:var(--brand-teal);
  --muted:var(--text-secondary);
  --rule:#DED7C8;
  --accent:var(--brand-teal);
  --accent-on:var(--brand-cream);   /* text on a teal surface */
  --marker:var(--brand-gold-deep);  /* eyebrows, dividers, active markers */
  --gold:var(--brand-gold);         /* pure gold: rules, hairlines, details */
  --alert:var(--brand-alert);
  --shadow:rgba(7,27,46,.07);
  --logo-plate:transparent;
  --lockup:url("img/brand/lockup-stacked-light.png");

  /* ---- TYPE --------------------------------------------------------------
     Playfair Display for large headings, Source Sans 3 for everything else
     including navigation and labels. Monospace survives in exactly one place
     — the BibTeX block, where it is functional.
     --------------------------------------------------------------------- */
  --display:"Playfair Display",Georgia,"Times New Roman",serif;
  --body:"Source Sans 3","Source Sans Pro",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

  --rail:236px;

  /* ---- fluid scale (unchanged) ---- */
  --type-scale:1;
  --util:calc(clamp(0.75rem, 0.714rem + 0.16vw, 0.894rem) * var(--type-scale));
  --t-body:calc(clamp(1rem, 0.918rem + 0.36vw, 1.323rem) * var(--type-scale));
  --t-h3:calc(clamp(1.062rem, 0.972rem + 0.4vw, 1.422rem) * var(--type-scale));
  --t-h2:calc(clamp(1.438rem, 1.22rem + 0.97vw, 2.311rem) * var(--type-scale));
  --t-h1:calc(clamp(1.875rem, 1.294rem + 2.58vw, 4.194rem) * var(--type-scale));

  --pad-section:clamp(2.5rem, 1.847rem + 2.9vw, 5.109rem);
  --pad-hero:clamp(3rem, 1.911rem + 4.84vw, 7.356rem);

  /* WIDENED (v2.9). Was clamp(34rem, 28.5rem + 14.67vw, 47rem).
     The brief: the hero headline should break into three lines, not four.
     That is a width problem, not a type problem — at the old measure the
     sentence needs four lines at every viewport. Measured from the rendered
     word widths, three lines require roughly 780px at the size the headline
     actually renders on a laptop, so the slope is steeper and the ceiling
     higher. The ceiling is set against the headline's own maximum size: at
     very wide viewports --t-h1 hits its 4.194rem cap and the words grow about
     17%, which needs ~920px to still fit three lines. Hence 58rem.
     KNOWN COST, stated plainly: this widens EVERY block on the site, because
     one measure governs all of them. Body paragraphs now run roughly 95-100
     characters per line on a laptop, against the 45-75 that is normally
     considered comfortable for sustained reading. That is the trade being
     made deliberately in exchange for the three-line headline. */
  --measure:clamp(34rem, 28.5rem + 25vw, 58rem);
}

/* ---- SEMANTIC TOKENS (dark) ---------------------------------------------
   Plain teal on navy measures 2.04:1 — unusable, exactly as the brief warns.
   Links and headings switch to a brightened teal at 7.03:1. Gold gains
   contrast on navy (7.06:1) so it can carry small text here as it cannot on
   cream.
   ------------------------------------------------------------------------ */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --ground:var(--brand-navy);
    --panel:#0E2A42;
    --ink:var(--brand-ivory);
    --heading:var(--brand-ivory);
    --muted:#98A3AA;
    --rule:#1B3A55;
    --accent:#4FB3B8;
    --accent-on:var(--brand-navy);
    --marker:var(--brand-gold);
    --gold:var(--brand-gold);
    --alert:#EE9179;
    --shadow:rgba(0,0,0,.45);
    --logo-plate:var(--brand-cream);
    --lockup:url("img/brand/lockup-stacked-navy.png");
  }
}
:root[data-theme="dark"]{
  --ground:var(--brand-navy);
  --panel:#0E2A42;
  --ink:var(--brand-ivory);
  --heading:var(--brand-ivory);
  --muted:#98A3AA;
  --rule:#1B3A55;
  --accent:#4FB3B8;
  --accent-on:var(--brand-navy);
  --marker:var(--brand-gold);
  --gold:var(--brand-gold);
  --alert:#EE9179;
  --shadow:rgba(0,0,0,.45);
  --logo-plate:var(--brand-cream);
  --lockup:url("img/brand/lockup-stacked-navy.png");
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}

body{
  margin:0;
  background:var(--ground);
  color:var(--ink);
  font-family:var(--body);
  font-size:var(--t-body);
  line-height:1.62;
  font-weight:380;
  -webkit-font-smoothing:antialiased;
}

a{color:var(--accent);text-underline-offset:3px;text-decoration-thickness:1px}
a:hover{color:var(--marker)}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}

h1,h2,h3,h4{font-family:var(--display);font-weight:500;letter-spacing:-.004em;text-wrap:balance;color:var(--heading)}

.visually-hidden{
  position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}

.skip{
  position:absolute;left:-9999px;top:0;
  background:var(--ink);color:var(--ground);
  padding:.7rem 1rem;font-family:var(--body);font-size:var(--util);z-index:99;
}
.skip:focus{left:0}

/* ==========================================================================
   Mobile top bar + scroll progress
   ========================================================================== */

.topbar{
  position:sticky;top:0;z-index:40;
  background:var(--ground);
  border-bottom:1px solid var(--rule);
}
.topbar__inner{
  display:flex;align-items:center;flex-wrap:wrap;gap:.45rem 1rem;
  padding:.7rem 1.2rem;
}
/* Mobile keeps the monogram plus the name set in the body face. The brief is
   explicit that the full script must not be shrunk into small spaces. */
.topbar__name{
  display:inline-flex;align-items:center;gap:.55rem;
  font-family:var(--body);font-size:calc(var(--t-h3) * .92);font-weight:600;
  color:var(--ink);text-decoration:none;flex:none;
}
.topbar__mark{
  width:1.9rem;height:1.9rem;border-radius:50%;flex:none;
}
/* Below 560px the links drop to their own full-width row and wrap, so no
   navigation item can end up scrolled out of sight. Above that they sit
   inline on a single row. */
.topbar__nav{flex:1 0 100%;order:3;min-width:0}
@media (min-width:560px){
  .topbar__nav{flex:0 1 auto;order:0;margin-left:auto}
}
.topbar__nav ul{
  display:flex;flex-wrap:wrap;gap:.4rem 1.05rem;list-style:none;margin:0;padding:0;
}
.topbar__nav a{
  font-family:var(--body);font-size:var(--util);letter-spacing:.02em;
  color:var(--muted);text-decoration:none;white-space:nowrap;
  padding:.25rem 0;display:block;
}
.topbar__nav a:hover{color:var(--ink)}
.topbar__nav a[aria-current="page"]{color:var(--marker)}
.progress{height:2px;background:transparent}
.progress span{display:block;height:100%;width:0;background:var(--marker);transition:width .18s linear}

/* ==========================================================================
   Desktop rail — site nav, page contents, scroll progress
   ========================================================================== */

.rail{display:none}

@media (min-width:1080px){
  .topbar{display:none}

  .rail{
    display:flex;flex-direction:column;
    grid-column:1;
    position:sticky;top:0;height:100vh;
    padding:2.6rem 1rem 2rem 0;
    overflow-y:auto;overscroll-behavior:contain;
  }
  /* The lockup is a background image so it can follow the theme token — a
     plain <img> could not switch with the manual dark-mode toggle. The link's
     accessible name comes from visually-hidden text inside it. */
  .rail__logo{
    display:block;
    width:100%;max-width:186px;
    aspect-ratio:760 / 599;
    background:var(--lockup) no-repeat center / contain;
    /* clear space of roughly one "I" stroke on every side, as the brief asks */
    margin:0 0 .9rem;
  }
  .rail__role{
    font-family:var(--body);font-size:var(--util);letter-spacing:.06em;
    color:var(--muted);margin:0 0 2rem;
  }
  .rail__label{
    font-family:var(--body);font-weight:600;font-size:var(--util);letter-spacing:.14em;
    text-transform:uppercase;color:var(--muted);margin:0 0 .9rem;
  }
  .rail__nav ul{list-style:none;margin:0 0 2.2rem;padding:0}
  .rail__nav a{
    display:block;font-family:var(--body);font-size:var(--util);
    color:var(--muted);text-decoration:none;padding:.28rem 0;
    transition:color .2s ease;
  }
  .rail__nav a:hover{color:var(--ink)}
  .rail__nav a[aria-current="page"]{color:var(--marker)}

  .axis{position:relative;padding-left:1.5rem;flex:0 0 auto}
  .axis__line{position:absolute;left:0;top:.4rem;bottom:.4rem;width:1px;background:var(--rule)}
  .axis__fill{
    position:absolute;left:0;top:.4rem;width:1px;height:0;
    background:var(--marker);transition:height .18s linear;
  }
  .axis ul{list-style:none;margin:0;padding:0}
  .axis a{
    display:block;font-family:var(--body);font-size:var(--util);
    color:var(--muted);text-decoration:none;padding:.3rem 0;
    transition:color .2s ease;
  }
  .axis a:hover{color:var(--ink)}
  .axis a[aria-current="true"]{color:var(--marker)}
  .axis__num{font-variant-numeric:tabular-nums;opacity:.7;margin-right:.5rem}
}

/* ---- reader controls: theme + text size ---- */
.controls{
  display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;
  /* One height for every control here, and it tracks the reader's text-size
     choice — otherwise the toggle grows at 145% and the A buttons don't. */
  --control-h:calc(2rem * var(--type-scale));
}
.rail .controls{margin-top:1.6rem;align-self:flex-start}
.topbar .controls{flex:none;margin-left:auto}

/* stretch, not baseline: the three A's are different sizes, and baseline
   alignment made each button a different height. */
.sizes{
  display:flex;align-items:stretch;box-sizing:border-box;min-height:var(--control-h);
  border:1px solid var(--rule);border-radius:2px;
}
.sizebtn{
  display:flex;align-items:center;justify-content:center;
  min-width:2.1rem;
  background:none;border:0;cursor:pointer;color:var(--muted);
  font-family:var(--body);line-height:1;
  padding:0 .35rem;
  transition:color .15s ease;
}
.sizebtn + .sizebtn{border-left:1px solid var(--rule)}
.sizebtn:nth-child(1){font-size:calc(.82rem * var(--type-scale))}
.sizebtn:nth-child(2){font-size:calc(1rem * var(--type-scale))}
.sizebtn:nth-child(3){font-size:calc(1.2rem * var(--type-scale))}
.sizebtn:hover{color:var(--ink)}
.sizebtn[aria-pressed="true"]{color:var(--ground);background:var(--ink)}

@media print{ .controls{display:none!important} }

/* theme toggle */
.themetoggle{
  display:inline-flex;align-items:center;
  min-height:var(--control-h);
  font-family:var(--body);font-size:var(--util);line-height:1;
  background:none;border:1px solid var(--rule);color:var(--muted);
  padding:0 .6rem;cursor:pointer;border-radius:2px;
}
.themetoggle:hover{color:var(--ink);border-color:var(--muted)}
/* Spacing and placement belong to .controls now — leaving margins on the
   toggle itself pushed it out of line with the text-size buttons. */
.topbar .themetoggle{flex:none}

/* Touch targets. Must come after the .themetoggle rule above, or the base
   min-height wins on equal specificity. */
@media (pointer:coarse){
  .themetoggle,.sizes{min-height:max(2.75rem, var(--control-h))}
  .sizebtn{min-width:2.75rem}
}


/* ==========================================================================
   Shell + generic sections
   ========================================================================== */

.shell{
  max-width:calc(var(--measure) + 2.6rem);
  margin:0 auto;
  padding:0 1.2rem 5rem;
}

/* Desktop: the page becomes a two-column grid — rail, then content — and the
   whole thing is centred as one unit. The rail can no longer drift away from
   the text on a wide monitor. */
@media (min-width:1080px){
  body{
    display:grid;
    grid-template-columns:var(--rail) minmax(0,1fr);
    column-gap:3rem;
    max-width:clamp(1060px, 86vw, 1320px);
    margin:0 auto;
    padding:0 2rem;
  }
  .shell{
    grid-column:2;
    max-width:none;
    margin:0;
    padding:0 0 5rem;
  }
}

/* Exactly the body measure — not a pixel wider. The hero, every section
   heading and every paragraph on the site share one left edge and one right
   edge. An earlier +3rem here made the title overhang the body by 48px. */
/* Utility row: sits at the top right of the content column, on the same
   measure as everything else so the right edge still lines up. The hero's top
   padding is reduced when this row precedes it, otherwise the two stack and
   push the headline down the page. */
.utility{
  display:flex;justify-content:flex-end;
  max-width:var(--measure);
  padding:1.15rem 0 0;
}
.utility__link{
  display:inline-flex;align-items:center;
  min-height:var(--control-h,2rem);
  font-family:var(--body);font-weight:600;font-size:var(--util);
  letter-spacing:.06em;
  color:var(--muted);text-decoration:none;
  border-bottom:1px solid var(--rule);
  padding:0 .1rem;
  transition:color .15s ease,border-color .15s ease;
}
.utility__link:hover{color:var(--marker);border-color:var(--gold)}
@media (pointer:coarse){ .utility__link{min-height:2.75rem} }
@media print{ .utility{display:none} }

.utility + .hero{padding-top:calc(var(--pad-hero) * .45)}

.hero{padding:var(--pad-hero) 0 2.6rem;max-width:var(--measure)}
.hero__eyebrow{
  font-family:var(--body);font-size:var(--util);letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted);margin:0 0 1.8rem;
}
.hero__thesis{
  /* JUSTIFIED ON PURPOSE — owner's decision, 17 Aug 2026 (v2.7).
     Supersedes the earlier "headings are never justified" rule for this one
     element. The brief: the headline's right edge must land flush with the
     body column, the way the paragraph below it does. `text-wrap:balance`
     did the opposite — it pulled all four lines in to ~570px inside a 700px
     column, leaving a 120px wedge of empty space down the right side.

     Balance is cancelled explicitly (`text-wrap:wrap`) because the shared
     h1–h4 rule at the top of this file sets it, and balance fights justify.

     KNOWN COST, stated plainly: justification distributes the leftover space
     into the word gaps, and display type has few words per line to spread it
     across. The worst case here is the first line, which cannot pull "where"
     up from line two — roughly 138px of slack over two spaces. `hyphens:auto`
     is doing real work below: it lets long words break so lines pack closer
     to full before wrapping, which is the main defence against holes.

     IF THE GAPS BOTHER YOU: shrink the headline slightly. Smaller type fits
     more words per line, which is what actually closes the holes. Change the
     1 below to .92 or .88 and the slack drops sharply. It is the one knob
     that matters here. */
  text-align:justify;
  text-justify:inter-word;
  text-wrap:wrap;
  hyphens:auto;
  -webkit-hyphens:auto;
  /* Headline hyphenation is more conservative than body prose: a word must be
     8 characters before it may break at all, with at least 4 either side, so
     short words are never chopped for the sake of a flush edge. */
  hyphenate-limit-chars:8 4 4;
  font-size:calc(var(--t-h1) * 1);
  line-height:1.14;
  /* FITTED WIDTH (v2.7). initHeroFit() in site.js measures the width at which
     the text breaks with the least left-over space and writes it here. The
     fallback is the full column, so with JS off this is exactly the justified
     full-width headline and nothing looks broken. `auto` margins centre the
     fitted block inside the column — his call, made knowing the left edge no
     longer lines up with the eyebrow and the paragraph below. */
  width:var(--thesis-width, 100%);
  max-width:100%;
  margin:0 auto 1.6rem;
}
/* Last line of a justified block stays ragged — stretching a two-word final
   line across the full column is the one thing that always looks broken. */
.hero__thesis{text-align-last:left}

/* Print gets the full column back: the measured pixel width belongs to a
   screen viewport and means nothing on paper. */
@media print{
  .hero__thesis{width:auto;margin-left:0;margin-right:0;text-align:left}
}

/* MOBILE GUARD — currently OFF, one uncomment away from ON.
   Below 640px the column is narrow enough that a line may hold only two or
   three words, and justification has almost nothing to spread the slack
   across. If the headline looks gappy on a phone, uncomment this block and
   the narrow view reverts to balanced, ragged-right; desktop keeps justify.
@media (max-width:639px){
  .hero__thesis{text-align:left;text-wrap:balance;hyphens:manual;width:auto;margin-left:0;margin-right:0}
}
*/
.hero__thesis em{font-style:italic;color:var(--accent)}
.hero__sub{font-size:calc(var(--t-body) * .96);color:var(--muted);margin:0 0 2rem}

.section{
  max-width:var(--measure);
  padding:var(--pad-section) 0 .6rem;
  border-top:1px solid var(--rule);
  position:relative;
}
/* Was measure + 8rem, which made the publication and news lists stick out
   128px past every other block. One measure for everything. */
.section--wide{max-width:var(--measure)}
.section:first-of-type{border-top:none}
.section__num{
  font-family:var(--body);font-weight:600;font-size:var(--util);letter-spacing:.16em;
  text-transform:uppercase;color:var(--marker);
  display:block;margin-bottom:.9rem;
}
.section h2{font-size:var(--t-h2);line-height:1.18;margin:0 0 1.4rem}
.section h3{font-size:var(--t-h3);margin:2rem 0 .7rem}
.section p{margin:0 0 1.1rem}
.section p:last-child{margin-bottom:0}
.section ul,.section ol{margin:0 0 1.1rem;padding-left:1.2rem}
.section li{margin-bottom:.4rem}

/* --------------------------------------------------------------------------
   Justified body prose.
   `hyphens:auto` is doing real work here — without it, justifying a column
   this narrow opens ugly gaps between words. Monospace labels, captions,
   metadata and navigation stay ragged-right on purpose: justifying short
   fragments looks worse than leaving them alone.
   To go back to ragged-right, change `justify` to `left` in this one rule.
   -------------------------------------------------------------------------- */
.section p,
.bio__text p,
.quote blockquote p,
.hero__sub{
  text-align:justify;
  text-justify:inter-word;
  hyphens:auto;
  -webkit-hyphens:auto;
  /* Break earlier and more often than the browser default, which closes up
     the worst of the word gaps in narrow columns. */
  hyphenate-limit-chars:6 3 3;
}

.note{
  font-family:var(--body);font-size:var(--util);line-height:1.75;
  color:var(--muted);border-left:1px solid var(--marker);
  padding:.15rem 0 .15rem .8rem;margin:0 0 1.4rem;
}
@media (min-width:1480px){
  .note--margin{position:absolute;left:calc(var(--measure) + 2.6rem);width:11rem;margin:0}
}

/* --------------------------------------------------------------------------
   Long uppercase, letter-spaced labels cannot wrap mid-word, so at the largest
   text size on a narrow phone a single word like TELECOMMUNICATIONS can be
   wider than the screen. Allow these — and only these — to break anywhere.
   -------------------------------------------------------------------------- */
/* Long unbreakable strings — email addresses, DOIs, URLs — inside the
   label/value lists. Source Sans sets wider than the old body face, which
   tipped imanulhuq@gmail.com past a 320px screen at the largest text size. */
/* Label / value rows — education, contact details, awards, talks, competencies.
   A description list, not a bulleted list: <dt> and <dd> are block-level, so
   the label and the value can never run together even if this stylesheet
   fails to load. They previously did exactly that — "Emailimanulhuq@gmail.com"
   — when these rules went missing, which is a fragility worth designing out
   rather than patching. */
.factlist{margin:0;padding:0}
.factlist > div{
  display:grid;gap:.35rem .9rem;
  padding:.7rem 0;
  border-bottom:1px solid var(--rule);
  font-size:calc(var(--t-body) * .94);
}
.factlist > div:last-child{border-bottom:0}
@media (min-width:640px){
  .factlist > div{grid-template-columns:10rem 1fr;gap:.2rem .9rem}
}
.factlist dt{
  font-family:var(--body);font-weight:600;font-size:var(--util);
  letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);padding-top:.25rem;
}
.factlist dd{margin:0}
.factlist dd,
.factlist a{overflow-wrap:anywhere}

.section__num,
.certs__group,
.affil__label,
.rail__label,
.pubfilters__label,
.pub__flag,
.pillar__tag,
.talk__kind,
.hero__eyebrow{
  overflow-wrap:anywhere;
}

/* Login and private pages have no rail, so the column centres itself. */
.shell--plain{max-width:calc(var(--measure) + 2.4rem);margin:0 auto;padding-left:1.2rem;padding-right:1.2rem}
@media (min-width:1080px){ .shell--plain{grid-column:1 / -1;max-width:calc(var(--measure) + 2.4rem);margin:0 auto} }

/* private.html starts hidden so its contents never flash before the guard
   redirects; site.js removes the attribute once the session check passes. */
[hidden]{display:none !important}

/* ==========================================================================
   Contact form
   ========================================================================== */

.cform{margin:1.4rem 0 0;max-width:34rem}
.cform__field{margin:0 0 1.3rem;border:0;padding:0}
.cform__field > label,
.cform__field legend{
  display:block;
  font-family:var(--body);font-size:var(--util);letter-spacing:.06em;
  color:var(--muted);margin:0 0 .4rem;padding:0;
}
.cform input[type="text"],
.cform input[type="email"],
.cform input[type="password"],
.cform textarea{
  width:100%;
  font-family:var(--body);font-size:calc(var(--t-body) * .96);
  color:var(--ink);background:var(--panel);
  border:1px solid var(--rule);border-radius:2px;
  padding:.6rem .7rem;
}
.cform textarea{resize:vertical;min-height:8rem;line-height:1.55}
.cform input:focus-visible,
.cform textarea:focus-visible{outline:2px solid var(--marker);outline-offset:1px}
.cform [aria-invalid="true"]{border-color:var(--alert)}

.cform__radios{display:flex;flex-direction:column;gap:.15rem}
.cform__radio{display:flex;align-items:flex-start;gap:.6rem;padding:.35rem 0}
.cform__radio input{
  flex:none;margin:.3rem 0 0;width:1rem;height:1rem;accent-color:var(--accent);
}
.cform__radio label{
  font-size:calc(var(--t-body) * .94);line-height:1.45;color:var(--ink);cursor:pointer;
}

/* The honeypot: off-screen, unfocusable, invisible to assistive tech. Not
   display:none — some bots skip fields that are display:none. */
.cform__trap{
  position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;
}

.cform__short{max-width:7rem}
.cform__hint{
  font-family:var(--body);font-size:calc(var(--util) * .95);line-height:1.55;
  color:var(--muted);margin:.4rem 0 0;
}

.cform__actions{display:flex;flex-wrap:wrap;align-items:center;gap:.9rem;margin-top:1.4rem}
.cform__note{
  font-family:var(--body);font-size:calc(var(--util) * .95);color:var(--muted);margin:0;
}
.cform__err{
  font-family:var(--body);font-size:calc(var(--util) * .95);line-height:1.55;
  color:var(--alert);margin:.4rem 0 0;
}
/* Errors are marked by a rule and a word, never by colour alone. */
.cform__err::before{content:"\2192\00a0"}

.cform__status{
  font-family:var(--body);font-size:calc(var(--util) * .95);line-height:1.6;
  margin:1rem 0 0;padding:0;
}
.cform__status--ok{color:var(--accent);border-left:2px solid var(--accent);padding-left:.7rem}
.cform__status--err{color:var(--alert);border-left:2px solid var(--alert);padding-left:.7rem}

#cf-captcha:not(:empty){margin:0 0 1.2rem}

@media print{ .cform{display:none} }

/* ==========================================================================
   Per-section Top / Home links
   ========================================================================== */

.secnav{
  display:flex;justify-content:flex-end;gap:1.1rem;
  margin:1.6rem 0 0;padding-top:.7rem;
  border-top:1px solid var(--rule);
}
.secnav__link{
  display:inline-flex;align-items:baseline;gap:.35rem;
  font-family:var(--body);font-size:var(--util);letter-spacing:.06em;
  color:var(--muted);text-decoration:none;
  padding:.35rem .25rem;
  transition:color .15s ease;
}
.secnav__link:hover{color:var(--marker)}
/* On touch screens these are the smallest tap targets on the page, so give
   them the full 44px recommended height rather than the 24px minimum. */
@media (pointer:coarse){
  .secnav{gap:1.6rem}
  .secnav__link{min-height:2.75rem;align-items:center;padding-left:.5rem;padding-right:.5rem}
}
.secnav__mark{font-size:.9em}

@media print{ .secnav{display:none} }

/* ==========================================================================
   Hero byline and the explain/apply/test/reflect cycle
   (both came from the original teaching-philosophy page and had no rules
    here, so they were rendering with browser defaults)
   ========================================================================== */

.byline{
  font-family:var(--body);font-size:var(--util);line-height:2;
  color:var(--muted);margin:0;
}
.byline strong{
  display:block;
  font-family:var(--body);font-size:calc(var(--t-h3) * .92);font-weight:500;
  color:var(--ink);letter-spacing:0;margin-bottom:.35rem;
}
.byline a{text-decoration:none;border-bottom:1px solid var(--rule)}
.byline a:hover{border-color:var(--marker)}

/* It is a real sequence, so it stays an <ol>. The numbers are a CSS counter:
   the markup used to carry "01", "02" spans of its own, which the browser's
   list numbering then duplicated — "1. 01 Explain". */
.cycle{
  display:flex;flex-wrap:wrap;gap:.7rem 0;
  list-style:none;counter-reset:cycle;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
  margin:0 0 2.4rem;padding:.9rem 0;
}
.cycle li{
  counter-increment:cycle;
  flex:1 1 7rem;min-width:0;
  display:flex;gap:.5rem;align-items:baseline;
  font-family:var(--body);font-size:var(--util);letter-spacing:.04em;
  color:var(--ink);
}
.cycle li::before{
  content:counter(cycle,decimal-leading-zero);
  color:var(--marker);font-size:.85em;flex:none;
}

/* ==========================================================================
   Buttons and links
   ========================================================================== */

/* Secondary button: transparent with a teal border. Primary (.btn--accent):
   solid teal with cream text. Gold is the hover detail on both, never the
   fill — at 2.31:1 on cream it cannot carry text. */
.btn{
  display:inline-flex;align-items:center;gap:.4rem;
  font-family:var(--body);font-weight:600;font-size:var(--util);line-height:1;
  letter-spacing:.02em;
  padding:.55rem .85rem;
  background:none;border:1px solid var(--accent);border-radius:2px;
  color:var(--accent);text-decoration:none;cursor:pointer;
  transition:color .15s ease,border-color .15s ease,background-color .15s ease;
}
.btn:hover{border-color:var(--gold);color:var(--marker)}
.btn[aria-pressed="true"]{color:var(--accent-on);background:var(--accent);border-color:var(--accent)}
.btn[aria-pressed="true"]:hover{border-color:var(--gold);color:var(--accent-on)}
.btn--accent{color:var(--accent-on);background:var(--accent);border-color:var(--accent)}
.btn--accent:hover{background:var(--accent);border-color:var(--gold);color:var(--accent-on)}

.actions{display:flex;flex-wrap:wrap;gap:.5rem;margin:1.6rem 0 0}

/* ==========================================================================
   Publications
   ========================================================================== */

.pubfilters{
  display:flex;flex-wrap:wrap;gap:.45rem;align-items:center;
  margin:0 0 2rem;padding:0 0 1.4rem;border-bottom:1px solid var(--rule);
}
.pubfilters__label{
  font-family:var(--body);font-weight:600;font-size:var(--util);letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);margin-right:.4rem;
}

.pub{
  padding:1.6rem 0;
  border-bottom:1px solid var(--rule);
}
.pub:first-of-type{padding-top:0}
.pub__flag{
  font-family:var(--body);font-weight:600;font-size:var(--util);letter-spacing:.12em;
  text-transform:uppercase;color:var(--marker);display:block;margin-bottom:.5rem;
}
.pub__flag--published{color:var(--accent)}
.pub__title{
  font-family:var(--body);font-weight:500;font-size:var(--t-h3);line-height:1.35;
  margin:0 0 .45rem;letter-spacing:0;
}
.pub__authors{font-size:calc(var(--t-body) * .92);color:var(--muted);margin:0 0 .3rem}
.pub__authors .me{color:var(--ink);font-weight:500}
.pub__author-link{
  color:inherit;text-decoration:none;
  border-bottom:1px solid var(--rule);
}
.pub__author-link:hover{color:var(--marker);border-color:var(--marker)}
.pub__venue{font-size:calc(var(--t-body) * .92);color:var(--muted);margin:0 0 .9rem;font-style:italic}
.pub__actions{display:flex;flex-wrap:wrap;gap:.45rem}

.cite{
  margin-top:1rem;padding:1rem;
  background:var(--panel);border:1px solid var(--rule);border-radius:2px;
}
.cite__tabs{display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:.8rem}
.cite pre{
  margin:0 0 .8rem;padding:.8rem;
  background:var(--ground);border:1px solid var(--rule);border-radius:2px;
  font-family:var(--mono);font-size:var(--util);line-height:1.6;
  white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;
  max-height:22rem;overflow:auto;
}

.empty{
  font-family:var(--body);font-size:var(--util);color:var(--muted);
  padding:2rem 0;
}

/* ==========================================================================
   News
   ========================================================================== */

.news{list-style:none;margin:0;padding:0}
.news li{
  display:grid;gap:.45rem 1.4rem;
  padding:1.2rem 0;border-bottom:1px solid var(--rule);
}
@media (min-width:640px){
  .news li{grid-template-columns:9.5rem 1fr;gap:.2rem 1.4rem}
}
.news__date{
  font-family:var(--body);font-size:var(--util);letter-spacing:.04em;
  color:var(--marker);padding-top:.28rem;
}
.news__body{margin:0}
.news__body strong{font-weight:500}

/* ==========================================================================
   Testimonials
   ========================================================================== */

.quotes{display:grid;gap:1.2rem;margin:0;padding:0}
@media (min-width:900px){.quotes{grid-template-columns:1fr 1fr}}
.quote{
  margin:0;padding:1.4rem;
  background:var(--panel);border:1px solid var(--rule);border-radius:2px;
}
.quote blockquote{margin:0 0 1rem;font-size:calc(var(--t-body) * .96);line-height:1.62}
.quote blockquote p{margin:0 0 .8rem}
.quote blockquote p:last-child{margin:0}
.quote figcaption{
  font-family:var(--body);font-size:var(--util);line-height:1.7;color:var(--muted);
  border-top:1px solid var(--rule);padding-top:.8rem;
}

/* ==========================================================================
   Cards / research pillars
   ========================================================================== */

.pillars{display:grid;gap:1.2rem;margin:0 0 1rem;padding:0;list-style:none}
@media (min-width:900px){.pillars{grid-template-columns:repeat(3,1fr)}}
.pillar{
  padding:1.3rem;background:var(--panel);
  border:1px solid var(--rule);border-radius:2px;
}
.pillar h3{
  font-family:var(--body);font-size:calc(var(--t-h3) * .95);font-weight:500;
  margin:0 0 .5rem;letter-spacing:0;
}
.pillar p{font-size:calc(var(--t-body) * .92);color:var(--muted);margin:0}
.pillar__tag{
  font-family:var(--body);font-weight:600;font-size:var(--util);letter-spacing:.12em;
  text-transform:uppercase;color:var(--marker);display:block;margin-bottom:.6rem;
}

/* ==========================================================================
   Portrait
   ========================================================================== */

/* FLOATED (v2.8). The empty band to the right of the portrait was the whole
   problem: the image sat on its own line and the prose started underneath it,
   leaving roughly 190px x 480px of dead cream.

   Worth distinguishing this from the earlier attempt that got reverted. That
   one put the portrait and the prose in a two-column layout, so EVERY line of
   EVERY paragraph started 250px in and stayed short — the whole text block
   moved off the page's left edge. A float is different: only the lines that
   actually sit beside the image are shortened, and the moment the text clears
   the bottom of the portrait it returns to the same left edge as the headings
   and the paragraphs below. Nothing permanently loses its alignment.

   Body prose is justified, so those shortened lines have less room to absorb
   slack. `hyphens:auto` is already on for paragraphs and does the work here. */
.bio__portrait{
  float:left;
  /* Small top offset so the image's top edge sits on the first line's
     x-height rather than above the ascenders. */
  margin:.35rem 1.6rem .9rem 0;
  width:clamp(140px,26vw,190px);height:auto;
  aspect-ratio:1;object-fit:cover;object-position:50% 22%;
  border:1px solid var(--rule);border-radius:2px;
  background:var(--panel);
}

/* The fact list must never ride up into the float's right-hand gutter — a
   definition list wrapping around a photograph reads as a layout accident. */
#about .factlist{clear:both}

/* Below 560px the column is too narrow to give up 140px to a float: the
   wrapped lines would be four or five words wide and justification would
   tear them apart. Revert to the stacked arrangement there. */
@media (max-width:559px){
  .bio__portrait{float:none;margin:0 0 1.4rem}
}

/* ---- award figure ---- */
.medal{margin:0;flex:0 0 auto;width:clamp(150px,40vw,200px)}
.medal img{
  display:block;width:100%;height:auto;aspect-ratio:1;object-fit:cover;
  border:1px solid var(--rule);border-radius:2px;
}
.medal figcaption{
  font-family:var(--body);font-size:calc(var(--util) * .95);line-height:1.6;
  color:var(--muted);margin-top:.55rem;text-wrap:pretty;
}

/* ==========================================================================
   Public mentions
   Same visual grammar as the talks list — dated label, sans title, muted
   note — so the news page reads as one page rather than two designs.
   ========================================================================== */

.mentions{list-style:none;margin:0;padding:0}
.mention{
  padding:1.5rem 0;
  border-top:1px solid var(--rule);
}
.mention:first-child{border-top:0;padding-top:.4rem}
.mention__head{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:.5rem .9rem;
  margin-bottom:.4rem;
}
.mention__date{
  font-family:var(--body);font-size:var(--util);letter-spacing:.04em;color:var(--marker);
}
.mention__outlet{
  font-family:var(--body);font-weight:600;font-size:var(--util);letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);
}
.mention__title{
  font-family:var(--body);font-weight:500;font-size:var(--t-h3);line-height:1.35;
  letter-spacing:0;margin:0 0 .4rem;
}
.mention__title a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--rule)}
.mention__title a:hover{color:var(--marker);border-color:var(--marker)}
.mention__note{
  font-size:calc(var(--t-body) * .92);color:var(--muted);margin:0;text-wrap:pretty;
}
.mention__image{
  display:block;width:100%;max-width:26rem;height:auto;margin-top:1rem;
  border:1px solid var(--rule);border-radius:2px;
}

/* ==========================================================================
   Disclosure (the contact form opens from here)

   Built on <details>/<summary> rather than a scripted button: the open state,
   keyboard operation and the screen-reader announcement all come from the
   browser, and with JS disabled the form still opens. A hand-rolled toggle
   would have to reimplement aria-expanded, aria-controls and key handling to
   arrive at the same place, and its failure mode — JS missing, form hidden
   forever — is worse.

   NOTE FOR LATER: this is safe only because contact.captcha is "question",
   the arithmetic challenge drawn in site.js. A Cloudflare Turnstile widget
   rendered inside a closed <details> often measures itself at zero width and
   comes back broken. If contact.captcha is ever switched to "turnstile", the
   widget must be built on first open rather than at boot.
   ========================================================================== */

.disclose{margin-top:2.2rem}
.disclose__summary{
  display:flex;align-items:center;gap:.7rem;
  cursor:pointer;list-style:none;
  padding:.4rem 0;
}
/* Both spellings are needed: the pseudo-element for WebKit, list-style for
   everyone else. Without them the browser's own triangle sits beside ours. */
.disclose__summary::-webkit-details-marker{display:none}
.disclose__summary::marker{content:""}
.disclose__title{margin:0}
.disclose__summary:hover .disclose__title{color:var(--marker)}
.disclose__summary:focus-visible{
  outline:2px solid var(--marker);outline-offset:4px;border-radius:2px;
}

/* Chevron drawn in CSS — two borders rotated — so there is no icon font or
   extra request for one glyph. */
.disclose__chev{
  width:.55rem;height:.55rem;flex:0 0 auto;
  border-right:2px solid var(--marker);
  border-bottom:2px solid var(--marker);
  transform:rotate(45deg);transform-origin:50% 50%;
  margin-top:-.28rem;                /* optically centres it on the cap height */
  transition:transform .18s ease;
}
.disclose[open] .disclose__chev{transform:rotate(-135deg);margin-top:.14rem}
@media (prefers-reduced-motion:reduce){
  .disclose__chev{transition:none}
}

.disclose > .cform{margin-top:1.4rem}

/* ==========================================================================
   Social / scholarly profile icons
   ========================================================================== */

.social{margin:1.2rem 0 0}
.social__row{
  display:flex;flex-wrap:wrap;gap:.7rem;
  list-style:none;margin:0;padding:0;
}
.social__link{
  display:inline-flex;align-items:center;justify-content:center;
  width:2.1rem;height:2.1rem;
  color:var(--muted);border:0;text-decoration:none;
  transition:color .15s ease,transform .15s ease;
}
.social__link:hover{color:var(--marker);transform:translateY(-1px)}
.social__link svg{width:100%;height:100%;display:block}
.sitefoot .social__link{border-bottom:0}

/* ==========================================================================
   Talks
   ========================================================================== */

.talks{list-style:none;margin:0;padding:0}
.talk{padding:1.6rem 0;border-bottom:1px solid var(--rule)}
.talk:first-child{padding-top:0}
.talk__head{display:flex;flex-wrap:wrap;gap:.3rem .9rem;align-items:baseline;margin-bottom:.5rem}
.talk__date{
  font-family:var(--body);font-size:var(--util);letter-spacing:.04em;color:var(--marker);
}
.talk__kind{
  font-family:var(--body);font-weight:600;font-size:var(--util);letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);
}
.talk__title{
  font-family:var(--body);font-weight:500;font-size:var(--t-h3);line-height:1.35;
  letter-spacing:0;margin:0 0 .4rem;
}
.talk__venue{font-size:calc(var(--t-body) * .92);color:var(--muted);margin:0}
.talk__photo{
  display:block;width:100%;max-width:26rem;height:auto;margin-top:1rem;
  border:1px solid var(--rule);border-radius:2px;
}

/* ==========================================================================
   Certifications
   ========================================================================== */

.certs__group{
  font-family:var(--body);font-weight:600;font-size:var(--util);letter-spacing:.14em;
  text-transform:uppercase;color:var(--marker);font-weight:400;
  margin:2rem 0 .8rem;
}
.certs__group:first-of-type{margin-top:.6rem}
.certs{list-style:none;margin:0;padding:0}
.cert{
  display:flex;flex-direction:column;gap:.35rem;
  padding:.85rem 0;border-bottom:1px solid var(--rule);
}
.cert__title{font-size:calc(var(--t-body) * .96);line-height:1.45;text-wrap:pretty}
.cert__meta{
  font-family:var(--body);font-size:var(--util);line-height:1.6;color:var(--muted);
}
.cert__note{
  font-size:calc(var(--t-body) * .9);font-style:italic;color:var(--muted);line-height:1.5;
}

/* ==========================================================================
   Figure rows (paired photographs with captions)
   ========================================================================== */

.figrow{display:grid;gap:1.4rem;margin:0 0 1.4rem;padding:0;list-style:none}
@media (min-width:640px){.figrow{grid-template-columns:1fr 1fr}}
.figrow figure{margin:0}
.figrow img{
  display:block;width:100%;height:auto;
  border:1px solid var(--rule);border-radius:2px;
}
/* Photographs of different shapes sit better matched on height than on
   width — the captions then line up instead of stepping. */
.figrow--level{display:flex;flex-wrap:wrap;gap:1.4rem;align-items:flex-start}
@media (min-width:640px){.figrow--level{grid-template-columns:none}}
.figrow--level figure{flex:0 1 auto;max-width:100%;min-width:0}
.figrow--level img{
  height:clamp(170px,24vw,250px);width:auto;max-width:100%;object-fit:contain;
}

.figrow figcaption{
  font-family:var(--body);font-size:calc(var(--util) * .95);line-height:1.6;
  color:var(--muted);margin-top:.55rem;text-wrap:pretty;
}

/* ==========================================================================
   Affiliations strip
   ========================================================================== */

.affil{
  /* The last block that ran to the column edge instead of stopping at the
     measure. Everything on the page now shares one left and one right edge. */
  max-width:var(--measure);
  border-top:1px solid var(--rule);
  /* Spacing matches .section exactly (v3.2). It used to be inverted: a large
     margin ABOVE the rule and only 2rem below it, so the rule sat ~100px
     under the Top/Home links and "AFFILIATIONS" crowded up ~32px beneath it —
     the mirror image of every other divider on the page, where the rule
     follows its predecessor closely and the next heading sits a full
     --pad-section below. Now the gap above comes from the preceding
     section's .6rem bottom padding, exactly as at a section-to-section
     boundary, and the gap below is --pad-section like every heading. */
  margin-top:0;
  padding-top:var(--pad-section);
}
.affil__label{
  font-family:var(--body);font-weight:600;font-size:var(--util);letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);font-weight:400;
  margin:0 0 1.1rem;
}
.affil__label + .affil__row + .affil__label{margin-top:2.4rem}

/* Column count is explicit rather than auto-filled (v2.9, retuned in v3.1).
   Six institutions in an auto-filled grid landed on FIVE columns at the wide
   measure, which pushed the sixth — GREC — onto a row of its own, orphaned
   under the row above. Five is the only count that does that: at 1, 2, 3 or 6
   columns GUSTO and GREC always end up side by side. So the counts are pinned
   and five is never reachable.
   Three is the widest used. With the logo now beside the text rather than
   above it, each item spends ~68px on the mark before a word appears, so more
   columns than three would leave "International Islamic University
   Chittagong" wrapping in a ribbon barely wider than the logo itself.
   One column below 560px: two horizontal items side by side on a phone give
   the text about 60px each. */
.affil__row{
  display:grid;
  grid-template-columns:1fr;
  gap:1.6rem 1.4rem;
  list-style:none;margin:0 0 .4rem;padding:0;
}
@media (min-width:560px){ .affil__row{grid-template-columns:repeat(2,1fr)} }
@media (min-width:900px){ .affil__row{grid-template-columns:repeat(3,1fr)} }

/* Logo LEFT, text beside it (v3.1) — was stacked, logo above name.
   Column counts came down with it: an item is now roughly 76px of logo plus
   a gap before the text even starts, so four columns would have left about
   100px for "International Islamic University Chittagong". Three columns at
   the widened measure gives each item ~257px, of which ~165px is text.
   Three still keeps GUSTO and GREC on the same row (3 + 3), which was the
   point of pinning the counts in the first place. */
.affil__item{
  display:flex;flex-direction:row;align-items:flex-start;
  gap:.85rem;min-width:0;
}
.affil__text{display:flex;flex-direction:column;gap:.3rem;min-width:0}
.affil__logo{
  flex:0 0 auto;                 /* never squeezed by a long institution name */
  width:clamp(52px,6vw,68px);height:auto;aspect-ratio:1;
  object-fit:contain;margin-bottom:0;   /* the gap is horizontal now */
  /* Padding is reserved in both themes so the row does not shift when the
     plate appears on toggle. box-sizing keeps the box the same size. */
  box-sizing:border-box;padding:.3rem;
  background:var(--logo-plate);border-radius:3px;
}
.affil__initials{
  display:flex;align-items:center;justify-content:center;
  font-family:var(--body);font-size:calc(var(--util) * 1.15);letter-spacing:.08em;
  color:var(--muted);
  border:1px solid var(--rule);
  background:var(--panel);
}
.affil__name{
  font-size:calc(var(--t-body) * .88);line-height:1.35;color:var(--ink);
  text-wrap:pretty;
}
.affil__name a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--rule)}
.affil__name a:hover{color:var(--marker);border-color:var(--marker)}
.affil__detail{
  font-family:var(--body);font-size:calc(var(--util) * .95);line-height:1.55;
  color:var(--muted);text-wrap:pretty;
}
.affil__refs{display:flex;flex-direction:column;gap:.12rem;margin-top:.15rem}
.affil__ref{
  font-family:var(--body);font-size:calc(var(--util) * .95);line-height:1.55;
  color:var(--muted);text-decoration:none;
  border-bottom:1px solid var(--rule);align-self:flex-start;
}
.affil__ref:hover{color:var(--marker);border-color:var(--marker)}

.affil__note{
  font-family:var(--body);font-size:calc(var(--util) * .95);line-height:1.75;
  color:var(--muted);border-left:1px solid var(--rule);
  padding:.2rem 0 .2rem .8rem;margin:1.2rem 0 0;max-width:42rem;
}

@media print{ .affil__logo{display:none} }

/* ==========================================================================
   Footer
   ========================================================================== */

.sitefoot{
  max-width:var(--measure);
  border-top:1px solid var(--rule);
  margin-top:3.4rem;padding-top:1.8rem;
  font-family:var(--body);font-size:var(--util);line-height:2;color:var(--muted);
}
.sitefoot a{text-decoration:none;border-bottom:1px solid var(--rule)}
.sitefoot a:hover{border-color:var(--marker)}
.sitefoot p{margin:0 0 .8rem;max-width:30rem}

/* ==========================================================================
   Motion + print
   ========================================================================== */

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    transition:none!important;animation:none!important;scroll-behavior:auto!important;
  }
}

@media print{
  .rail,.topbar,.skip,.themetoggle,.pubfilters,.pub__actions,.actions{display:none!important}
  body{background:#fff;color:#000;font-size:11pt;line-height:1.45}
  .shell{padding:0;max-width:none}
  .hero{padding:0 0 1.2rem}
  .section{padding:1.2rem 0 0;max-width:none}
  .note--margin{position:static;width:auto;margin:0 0 1rem}
  .cite{display:none}
  h1,h2,h3{page-break-after:avoid}
  .pub,.news li{page-break-inside:avoid}
  a{color:#000;text-decoration:none}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:9pt;color:#444}
}
