@font-face{font-family:'Bricolage Grotesque';src:url('../fonts/heading-bricolage-grotesque.woff2') format('woff2');font-style:normal;font-weight:100 900;font-display:optional}
@font-face{font-family:'Atkinson Hyperlegible';src:url('../fonts/body-atkinson-hyperlegible.woff2') format('woff2');font-style:normal;font-weight:100 900;font-display:optional}
/* ============================================================================
   DS-03 PRECISION MODULAR GRID  ·  Quillfield Tutoring
   Sheet 1 of 3 — tokens, fonts, reset, the twelve-column grid, the header.

   FINGERPRINT ROWS THIS SHEET CARRIES
     twelve-column modular grid · 72px indexed utility header ·
     numbered horizontal index · Literata headings / Atkinson Hyperlegible body

   PROFESSION VISUAL SYSTEM — RECOMMENDATION #5 (TUTORING)
     Only tokens change here. The master layout, the header, the hero
     composition, the footer, the navigation, the spacing scale and the
     signature rule-highlight effect are the DS-03 master, untouched.
     Palette: page #F2F1F8, surface #FCFCFD, text #191825, muted #46445A,
     action #484B0C (hover #5C5E0D, active #36380B), secondary accent #241D6D,
     selected fill #C0F0B2, frames #3C376C, review panel #E4E3F2, staff panel
     #DEDAEC, footer #211E38. Focus ring 3px solid #484B0C at 3px offset.

   TWO FONT FILES, WHICH IS THE CAP THE SPECIFICATION SETS.
     Literata (headings, labels, buttons) and Source Sans 3 (body,
     index numerals, form controls), both variable, both SIL Open Font Licence,
     both self-hosted latin subsets. The --sans token carries the heading face
     and --mono the body face, so every rule in the master keeps its role.

   CLS 0.
     Both faces are same-origin, preloaded from the page head, and declared
     font-display: optional, which cannot reflow text after first paint.
   ========================================================================= */





:root {
  /* ---- Recommendation #5 palette ---- */
  --page: #f2f1f8;
  --surface: #fcfcfd;
  --ink: #191825;
  --action: #484b0c;
  --action-hover: #5c5e0d;
  --action-active: #36380b;
  --second: #cdc9e0;
  --frame: #3c376c;
  --high: #241d6d;
  --select: #c0f0b2;
  --foot: #211e38;
  --foot-soft: #d9d7ea;

  /* Muted text measures 9.1:1 on the page ground; the accent used as text
     (--high-ink) measures 13.9:1, so neither is limited to large sizes. */
  --ink-soft: #46445a;
  --high-ink: #241d6d;

  /* Review panel and alternating module ground. */
  --alt: #e4e3f2;

  /* Staff panel and open-question surface. */
  --pale: #dedaec;

  /* Media direction: bright learning spaces, paper texture, diagram-led. */
  --media-filter: saturate(0.92) contrast(1.04);
  --media-overlay: linear-gradient(180deg, rgba(10, 12, 14, 0.02) 0%, rgba(10, 12, 14, 0.64) 100%);

  /* ---- families ---- */
  --sans:var(--catalog-font-body);
  --mono:var(--catalog-font-body);

  /* ---- the spacing scale: 4 8 12 16 24 32 48 64 96 128 ---- */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;
  --s9: 96px;
  --s10: 128px;

  /* ---- structure ---- */
  --maxw: 1280px;
  --measure: 68ch;
  --review: 52ch;
  --radius: 8px;
  --header: 56px;
  --gut: 16px;
  --section: 72px;
  --control: 44px;

  /* ---- motion ---- */
  --t: 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
  --t-long: 600ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* The responsive contract of section 7. Only the gutter ladder, the header
   height and the section rhythm are set here; every layout change belongs
   with the component it changes. */
@media (min-width: 360px) { :root { --gut: 18px; } }
@media (min-width: 375px) { :root { --gut: 20px; } }
@media (min-width: 414px) { :root { --gut: 24px; } }
@media (min-width: 768px) {
  :root { --gut: 36px; --header: 72px; --section: 80px; }
}
@media (min-width: 1024px) { :root { --gut: 48px; --section: 88px; } }

/* ================================ reset ================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header) + var(--s5));
}

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 1rem;
  line-height: 1.6;
  font-weight: 400;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

@media (min-width: 768px) { body { font-size: 1.0625rem; } }

h1, h2, h3, h4 {
  font-family: var(--sans);
  margin: 0;
  text-wrap: balance;
  /* Display sizes put single words in narrow columns: "principles" is 283px
     of ink at 64px and sits in a 260px label rail, "preparation" is 368px in
     a 363px service name. `text-wrap: balance` cannot break a word, so both
     overran their column silently -- no gate reads an element against its
     own box. Hyphenation is the typographic answer rather than a size
     exception, and the document declares lang="en" so the browser has a
     dictionary to do it with.

     The limit is what stops it becoming a disfigurement: unrestricted,
     Chromium broke "service" across two lines in a heading that had room for
     it, because hyphenation is a line-fitting preference and not only a
     last resort. Ten characters is longer than every ordinary word in these
     headings and shorter than the words that actually overran, so only the
     latter are ever broken, and never within four characters of either end. */
  hyphens: auto;
  hyphenate-limit-chars: 10 4 4;
}

h1 {
  font-size: clamp(2.25rem, 11vw, 3.75rem);
  line-height: 0.98;
  letter-spacing: -0.035em;
  font-weight: 700;
}

@media (min-width: 768px) {
  h1 { font-size: clamp(3.25rem, 7vw, 7rem); line-height: 0.94; }
}

h2 {
  font-size: clamp(2rem, 4vw, 4rem);
  line-height: 1.02;
  letter-spacing: -0.025em;
  font-weight: 700;
}

h3 {
  font-size: clamp(1.25rem, 2vw, 1.75rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  font-weight: 600;
}

h4 {
  font-size: 1.0625rem;
  line-height: 1.3;
  font-weight: 600;
}

p { margin: 0 0 var(--s4); max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

/* Emphasis inside body copy is set in the heading face at 600. */
strong, b { font-family: var(--sans); font-weight: 600; }

ul, ol { margin: 0; padding: 0; list-style: none; }

img { display: block; max-width: 100%; height: auto; }

/* The user-agent sheet gives every figure a 40px margin on each side and a
   1em margin below. That is 80px of width the grid never granted it, and it
   was shrinking both place images and every review row inside its own rule.
   Figures here are grid children or captioned frames, so the grid owns their
   spacing and the margin is reset once, globally. */
figure { margin: 0; }

/* An email address or a host name is one unbreakable run to the line breaker.
   The demo address is 32 characters and needs 309px of the 238px the legal
   module grants it at 320px, which pushed the whole document 30px wide. The
   break is allowed only where a normal break opportunity does not exist, so
   ordinary prose still wraps between words and only the long literal splits. */
p, li, dd, dt, td, th, address, blockquote, figcaption { overflow-wrap: break-word; }

/* The intrinsic width and height attributes on every image map to
   presentational CSS, so this height rule is load-bearing: without it a
   responsive image keeps its attribute height and distorts. */

a { color: var(--action); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--high-ink); }

/* One focus ring everywhere: 3px solid highlight at 3px offset. */
:focus-visible {
  outline: 3px solid var(--action);
  outline-offset: 3px;
  border-radius: 2px;
}

hr {
  border: 0;
  border-top: 1px solid var(--second);
  margin: var(--s6) 0;
}

.vh {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

.skip {
  position: absolute;
  left: var(--s4); top: -120px;
  z-index: 60;
  background: var(--ink);
  color: var(--page);
  padding: var(--s3) var(--s5);
  min-height: var(--control);
  display: inline-flex; align-items: center;
  font-family: var(--sans); font-size: 0.875rem;
  letter-spacing: 0.06em; text-transform: uppercase;
  text-decoration: none;
}
.skip:focus { top: var(--s2); color: var(--page); }

/* ========================= the twelve-column grid ======================== */

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gut);
}

/* One column below 768px, six from 768px, the full twelve from 1024px.
   Section 15 is explicit that above 1024px this must not quietly become an
   ordinary centred container, so every span below is a real column count
   against repeat(12, ...) and the page is composed of unequal spans that
   start on named columns rather than a repeated row of equal cards.
   minmax(0, 1fr) rather than 1fr: an auto minimum lets a long unbreakable
   string blow the track out past the viewport. */
/* .svm -- the services scope matrix -- is a grid of the same twelve columns
   but with its own row rhythm, so it joins the template rather than the gap. */
.grid,
.svm {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s6) var(--gut);
}

@media (min-width: 768px) {
  .grid,
  .svm { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .grid,
  .svm { grid-template-columns: repeat(12, minmax(0, 1fr)); }
}

@media (min-width: 768px) {
  /* A grid child that names no tablet span runs the full six columns rather
     than collapsing into one of them. Written with :where so the selector
     keeps the specificity of .grid alone, which lets the span classes below
     and the desktop spans further down override it on source order. Without
     this a block carrying only a desktop span rendered 86px wide between
     768px and 1023px, and about.html overflowed by 5px because of it. */
  .grid > :where(*),
  .svm > :where(*) { grid-column-end: span 6; }

  /* Every span class below sets the END edge only, and every start class in
     the desktop block sets the START edge only, so the two compose no matter
     which one the cascade reaches last. The shorthand cannot do that: it
     writes both edges, so grid-column-start on a later line replaced the
     span with a single track and the two .place figures rendered one 54px
     column wide with a zero-width image inside them. */
  .t2 { grid-column-end: span 2; }
  .t3 { grid-column-end: span 3; }
  .t4 { grid-column-end: span 4; }
}

@media (min-width: 1024px) {
  .d3 { grid-column-end: span 3; }
  .d4 { grid-column-end: span 4; }
  .d5 { grid-column-end: span 5; }
  .d6 { grid-column-end: span 6; }
  .d7 { grid-column-end: span 7; }
  .d8 { grid-column-end: span 8; }
  .d9 { grid-column-end: span 9; }
  .d10 { grid-column-end: span 10; }
  .d12 { grid-column-end: span 12; }
  .c2 { grid-column-start: 2; }
  .c4 { grid-column-start: 4; }
  .c6 { grid-column-start: 6; }
  .c7 { grid-column-start: 7; }
  .c8 { grid-column-start: 8; }
  .c9 { grid-column-start: 9; }
  .c10 { grid-column-start: 10; }
}

/* Five spacing utilities, named for the token they apply. They replaced the 88
   inline style="margin-top:*" attributes the ten pages were carrying, so the
   spacing scale is now the only place a vertical gap is decided and a change to
   --s5 actually moves the pages. Only the five values the pages use are
   declared -- validate.py fails a stylesheet on any class selector that matches
   no element anywhere, and a complete ten-step ladder would be exactly that. */
.mt-s2 { margin-top: var(--s2); }
.mt-s3 { margin-top: var(--s3); }
.mt-s4 { margin-top: var(--s4); }
.mt-s5 { margin-top: var(--s5); }
.mt-s6 { margin-top: var(--s6); }

/* Section rhythm: 72px mobile, 112px tablet, 144px desktop. */
.section { padding-block: var(--section); }
.section--tight { padding-block: calc(var(--section) * 0.55); }
.section--ruled { border-top: 1px solid var(--second); }

/* ==================== the 72px indexed utility header ==================== */

.head {
  position: sticky;
  top: 0;
  z-index: 50;
  /* A fixed height, not padding around content. The height is a token, so it
     cannot move when the font finishes loading, which is the failure section
     15 warns about. */
  height: var(--header);
  background: var(--page);
  border-bottom: 1px solid var(--second);
}

.head__in {
  height: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gut);
  display: flex;
  align-items: center;
  gap: var(--s4);
}

/* The header is INDEXED: the mark carries the business's own file number and
   every navigation item carries its two-digit index. */
.mark {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s2);
  text-decoration: none;
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: 1.0625rem;
  white-space: nowrap;
}
.mark:hover { color: var(--ink); }
.mark__no {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 0.8125rem;
  color: var(--ink-soft);
  letter-spacing: 0.04em;
}
.mark__tail { display: none; }
@media (min-width: 480px) { .mark__tail { display: inline; } }
@media (min-width: 1024px) and (max-width: 1279px) { .mark__tail { display: none; } }

.head__spacer { flex: 1 1 auto; }

@media (max-width: 479px) {
  .head__in { gap: var(--s2); }
  .idx-disclosure > summary { padding-inline: var(--s2); }
}

/* the desktop numbered horizontal index */
.idx { display: none; }

@media (min-width: 1024px) {
  .idx { display: block; }
  .idx__list { display: flex; align-items: center; gap: var(--s4); }
  .idx__link {
    display: inline-flex;
    align-items: baseline;
    gap: var(--s1);
    text-decoration: none;
    color: var(--ink);
    font-family: var(--sans);
    font-size: 0.8125rem;
    letter-spacing: 0.02em;
    padding-block: var(--s2);
    border-bottom: 1px solid transparent;
    transition: border-color var(--t), color var(--t);
  }
  .idx__no {
    font-family: var(--mono);
    letter-spacing: 0.04em;
    color: var(--ink-soft);
  }
  .idx__link:hover { color: var(--high-ink); border-bottom-color: var(--high); }
  .idx__link[aria-current="page"] { border-bottom-color: var(--ink); }
  .idx__link[aria-current="page"] .idx__no { color: var(--high-ink); }
}

@media (min-width: 1280px) {
  .idx__list { gap: var(--s5); }
}

/* Below 1024px the same numbered index is a native details element, so it
   opens and closes with no JavaScript at all. The script adds Escape, an
   outside pointerdown, a tab wrap and a width-change sync, and nothing else. */
.idx-disclosure { position: relative; }
@media (min-width: 1024px) { .idx-disclosure { display: none; } }

.idx-disclosure > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: var(--control);
  min-width: var(--control);
  padding-inline: var(--s3);
  border: 1px solid var(--ink);
  background: var(--page);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 0.875rem;
  line-height: 1.35;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.idx-disclosure > summary::-webkit-details-marker { display: none; }
.idx-disclosure > summary::marker { content: ""; }
.idx-disclosure[open] > summary { background: var(--ink); color: var(--page); }

.idx-disclosure__panel {
  position: absolute;
  right: 0;
  top: calc(100% + var(--s3));
  width: min(320px, calc(100vw - (2 * var(--gut))));
  background: var(--page);
  border: 1px solid var(--ink);
  padding: var(--s4);
  box-shadow: 0 18px 40px rgba(25, 24, 37, 0.14);
}

.idx-disclosure__link {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  min-height: var(--control);
  padding-block: var(--s2);
  text-decoration: none;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.9375rem;
  border-bottom: 1px solid var(--second);
}
.idx-disclosure__link:last-child { border-bottom: 0; }
.idx-disclosure__link:hover { color: var(--high-ink); }
.idx-disclosure__link[aria-current="page"] { color: var(--high-ink); }
.idx-disclosure__link .idx__no { color: var(--ink-soft); font-size: 0.8125rem; }

/* ============================== the emblem ==============================

   Nine modules on the three-by-three field the whole design is built from,
   with the north line rising through the first gutter in the highlight.
   The modules are `currentColor`; the line is the one literal, because the
   orange is what distinguishes this mark from a plain grid at tab size.

   Fixed boxes only.  `.mark` is already an inline flex row with a baseline
   alignment, so the mark is centred against the type rather than sitting
   on its baseline.                                                       */

.emb { display: block; flex: 0 0 auto; width: 20px; height: 20px; }

.mark .emb { align-self: center; }

.foot__label { display: flex; align-items: center; gap: 12px; }
.foot__label .emb { width: 28px; height: 28px; }

/* At 320px the header row is the mark, a spacer and the index disclosure, and
   the three do not fit once a mark is added. Below 360px the emblem TAKES OVER
   the index numeral's job -- it is the same three-by-three field the numeral
   sits in -- so `03` stands down and the row ends up narrower than it was
   before the mark existed. */
@media (max-width: 359px) {
  .mark { gap: 6px; }
  .mark .emb { width: 18px; height: 18px; }
  .mark__no { display: none; }
}

/* Selected text uses the Recommendation #5 selected fill. */
::selection { background: var(--select); color: var(--ink); }
/* Catalogue typography identity — headings and reading text. */
:root{--catalog-font-heading:'Bricolage Grotesque', 'Trebuchet MS', Arial, sans-serif;--catalog-font-body:'Atkinson Hyperlegible', system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;--sans:var(--catalog-font-body);--mono:var(--catalog-font-body)}
html body,input,select,textarea,button{font-family:var(--catalog-font-body)}
h1,h2,h3,h4,h5,h6,.display,.disp,.brand,.logo{font-family:var(--catalog-font-heading)}
