/* ==========================================================================
   THE PORCHLIGHT JOURNAL
   porchlight.v1.css  ·  the whole design system, one file, no imports
   --------------------------------------------------------------------------

   READ THIS BEFORE YOU CHANGE ANYTHING.

   1. THIS FILE IS SERVED IMMUTABLE.
      public/_headers ships /css/* with
      "Cache-Control: public, max-age=31536000, immutable".
      A visitor who has already loaded this file will NEVER fetch it again,
      and the Pages deploy token cannot purge the cache. So:

          DO NOT EDIT THIS FILE IN PLACE AND EXPECT ANYONE TO SEE IT.

      To ship a change, copy this file to /css/porchlight.v2.css, edit the
      copy, and update the <link rel="stylesheet"> in EVERY html file in
      public/ in the same commit. Keep the old file on disk so cached pages
      that still point at v1 keep rendering.

   2. WHO THIS IS FOR, AND WHY EVERY RULE BELOW LOOKS LIKE THAT.
      The reader is 55 to 80 years old, plus caregivers 45 to 65. Presbyopic,
      often reading through a progressive lens, on a phone held at arm's
      length, frequently inside the Facebook in-app browser, sometimes with a
      tremor, and they print articles to carry to a doctor's appointment.
      Every constraint below is downstream of that one sentence:

        · Body text is 21px on phones and 22px from tablet up, line-height
          1.75. Nothing on this site is set below 18px, and 18px happens only
          in monospace labels, which run visually small on the em.
        · Body text is a humanist SANS (Source Sans 3), not a serif. Large
          x-height, open apertures, wide counters. This is the single most
          legible thing you can put in front of a presbyopic eye at 21px,
          and it is also what makes this publication visibly a third thing
          next to its two sibling properties, both of which set body in a
          serif.
        · One column at every width. Nothing ever reflows into columns.
          Reading order on a 27 inch monitor is identical to a 320px phone.
        · Structure is drawn with rules and hairlines, never with drop
          shadows, never with rounded tinted panels. There is no card
          anywhere on this site and there must never be one.
        · Links are underlined in all four states, always, everywhere.
          A link that only shows itself on hover does not exist for a reader
          who navigates by tapping.
        · Every text pair on this site clears WCAG AAA (7:1). The lowest
          ratio anywhere is 8.07:1. See the palette block for the audited
          numbers, and re-audit before touching a colour token.
        · NOTHING MOVES. No transition, no animation, no keyframes, no
          geometric transform, no reveal on scroll, no parallax, no hover
          shift. A shaky tap must never chase a moving target.
        · Touch targets are at least 48px tall with real gaps between them.
        · The stock is warm cream, never pure white. White screens glare.
        · There is a real @media print block at the bottom of this file,
          because this reader prints.

   3. AUDIT LINE (run before every commit, from public/)
      Only declarations are audited, never the prose: this header names the
      banned properties on purpose, so the filter below keeps just the lines
      that end in a semicolon, which is every declaration and no comment.

        grep -E ";[[:space:]]*$" css/porchlight.v1.css | grep -cE \
        "box-shadow|border-radius|display: *contents|url\(|transition|animation|@keyframes|[^-]transform|text-decoration: *none|border[^:]*: *1px"

      Expected result: 0.

      Note the [^-] guard on transform: the only thing in this file that
      matches /transform/ is `text-transform: uppercase`, which is typography,
      not motion. There are zero motion properties in this file.

      For the pages themselves, from public/:
        grep -c "<script" *.html                 -> 0 (breath-report.html aside)
        grep -cE "<img|<picture" *.html          -> 0
        grep -P "[\x{2013}\x{2014}]" *.html      -> no output (no dashes)

   4. THINGS THAT ARE BANNED HERE ON PURPOSE, NOT BY OVERSIGHT.
        · box-shadow           (structure is rules; the focus ring is outline)
        · border-radius        (a rounded tinted block is a card)
        · any 1px border       (the smallest rule on this site is 2px)
        · display: contents    (it has broken a landing in the Facebook
                                in-app browser on this project before)
        · background-image / url()  (no images, no gradients, no icon fonts,
                                no SVG icons, no emoji as furniture)
        · @media (prefers-color-scheme: dark)
                               (every contrast number depends on the two
                                grounds staying exactly where they are;
                                the page ships color-scheme: light)
        · blockquote as a pull quote
                               (in a health niche a pulled quote reads as a
                                testimonial, and testimonials are prohibited
                                on this property. Use .aside-note.)

   5. FONTS
      Loaded from fonts.bunny.net only, a GDPR friendly Google Fonts proxy.
      Three faces, and each stack ends in a real system generic so a blocked
      or slow font request degrades to a fully legible page:
        Fraunces 700/900      display only, floor 24px
        Source Sans 3 400/600/700   all running text
        IBM Plex Mono 500/600  marking type only, never a sentence of prose
      No weight below 400 is ever requested, so a thin weight cannot be
      reached by accident.
   ========================================================================== */


/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root{
  color-scheme: light;

  /* ---- grounds --------------------------------------------------------
     --field is a GROUND AND NOTHING ELSE. Amber is never ink. Anyone who
     sets amber type breaks the page.
     --field is never a card: full measure, no radius, no shadow, 6px green
     top rule, hairline bottom, and it bleeds into the gutter.
     There is no grey in this palette. The quiet tone is a warm brown black.
     If a future edit introduces a neutral grey, it is wrong.               */

  --paper:      #FAF5E9;  /* the page. Genuinely warm stock, not "off white" */
  --field:      #F0DFB8;  /* amber printed band. A tint, never ink          */
  --desk:       #EDE6D3;  /* the surface the sheet lies on, >=64em only     */

  /* ---- inks ---------------------------------------------------------- */
  --ink:        #16130E;  /* all running text, all headings, heavy rules    */
  --ink-quiet:  #4A4034;  /* the hand line, colophon, captions.
                             ON --paper ONLY. Never on --field: it drops to
                             7.69:1 there, which is too tight to trust
                             across renderers and forced colour modes.      */

  /* ---- spot: porch green --------------------------------------------- */
  --spot:       #1D4634;  /* links, numerals, standing labels, 6px rule,
                             the knockout tab ground                        */
  --spot-deep:  #0E2A1E;  /* :hover / :focus / :active link colour          */
  --visited:    #4B2A55;  /* visited links                                  */

  /* ---- rules --------------------------------------------------------- */
  --rule-hair:  #7E7360;  /* every 2px separator, leader dots, writing lines */
  --rule-ink:   #16130E;  /* the 3px structural rule                        */
  --rule-plate: #1D4634;  /* the 6px signature rule                         */

  /* ---- audited contrast ------------------------------------------------
     ON --paper #FAF5E9
       --ink       17.03:1 AAA      --spot-deep  14.10:1 AAA
       --visited   10.96:1 AAA      --spot        9.76:1 AAA
       --ink-quiet  9.31:1 AAA      --rule-hair   4.28:1 non-text ok
     ON --field #F0DFB8
       --ink       14.07:1 AAA      --spot-deep  11.66:1 AAA
       --visited    9.06:1 AAA      --spot        8.07:1 AAA  <- the floor
       --rule-hair  3.54:1 non-text ok
     REVERSED on --spot #1D4634 (the knockout tab only)
       --paper      9.76:1 AAA
     ON --desk #EDE6D3 (nothing is ever set on the desk)
       --ink       14.87:1  --spot 8.52:1  --ink-quiet 8.13:1
     Lowest text ratio anywhere on this site: 8.07:1.
     --spot on --field is the first pair to re-check in any palette edit. */

  /* ---- faces --------------------------------------------------------- */
  --face-plate: "Fraunces", Georgia, "Times New Roman", Times, serif;
  --face-text:  "Source Sans 3", "Segoe UI", Tahoma, sans-serif;
  --face-mark:  "IBM Plex Mono", ui-monospace, Consolas, "Courier New", monospace;

  /* ---- type scale (root is 16px; one breakpoint, 48em) --------------- */
  --t-plate:   clamp(2.125rem, 1.35rem + 3.9vw, 4rem);    /* 34 -> 64px    */
  --t-numeral: clamp(3.25rem, 1.9rem + 6.5vw, 5.75rem);   /* 52 -> 92px    */
  --t-h1:      clamp(2.25rem, 1.55rem + 3.2vw, 3.25rem);  /* 36 -> 52px    */
  --t-h2:      clamp(1.75rem, 1.35rem + 2vw, 2.375rem);   /* 28 -> 38px    */
  --t-h3:      1.5rem;        /* 24px */
  --t-lead:    1.5rem;        /* 24px */
  --t-body:    1.3125rem;     /* 21px  <- the anchor */
  --t-note:    1.1875rem;     /* 19px */
  --t-mark:    1.125rem;      /* 18px, monospace only, the absolute floor */

  /* ---- measure and gutter -------------------------------------------- */
  --measure: 42rem;    /* 672px. ~64 chars at 21px, ~61 at 22px.
                          A slightly short measure is a deliberate kindness
                          to an eye that has to make the return sweep.      */
  --gutter:  1.25rem;  /* 20px on phone */

  /* ---- spacing scale -------------------------------------------------- */
  --s-1: .375rem;   /*   6px  tight label gaps            */
  --s-2: .75rem;    /*  12px  label to heading            */
  --s-3: 1.25rem;   /*  20px  block padding, phone gutter */
  --s-4: 2rem;      /*  32px  between related blocks      */
  --s-5: 3rem;      /*  48px  band padding-block          */
  --s-6: 4.5rem;    /*  72px  between .step sections      */
  --s-7: 6.5rem;    /* 104px  between major page regions  */
}

@media (min-width: 48em){
  :root{
    --t-h3:   1.625rem;    /* 26px */
    --t-lead: 1.625rem;    /* 26px */
    --t-body: 1.375rem;    /* 22px */
    --gutter: 2rem;
  }
}


/* ==========================================================================
   2. RESET
   Minimal on purpose. box-sizing everywhere is what guarantees no horizontal
   scroll at 320px once the full bleed bands start using negative margins.
   ========================================================================== */

*,
*::before,
*::after{ box-sizing: border-box; }

html{
  -webkit-text-size-adjust: 100%;   /* never let iOS re-scale our type */
  text-size-adjust: 100%;
}

body{
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--face-text);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.75;
  overflow-wrap: break-word;        /* a long word must never widen the page */
}

h1, h2, h3, h4, p, ul, ol, figure, blockquote{ margin: 0; }

ul, ol{ padding-inline-start: 1.4em; }

hr{ border: 0; margin: 0; }

img, svg{ max-width: 100%; height: auto; }  /* defensive: the journal ships none */


/* ==========================================================================
   3. LINKS AND FOCUS
   Underlined in all four states, without exception, including the nav, the
   index, the footer and the colophon. The underline carries the affordance,
   not the colour, because this palette uses green where the reader expects
   blue. If a real reader ever struggles, changing --spot to a deep blue
   restores the convention and touches nothing else on the site.
   No transition anywhere: the colour change is instant.
   ========================================================================== */

a{
  color: var(--spot);
  text-decoration-line: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: .18em;
  text-decoration-skip-ink: auto;
}

a:visited{ color: var(--visited); }

a:hover,
a:focus-visible,
a:active{
  color: var(--spot-deep);
  text-decoration-thickness: 3px;
}

/* The focus ring is an outline, never a box-shadow, and it is never removed
   anywhere in this file. 3px so it survives a cheap phone screen at arm's
   length. */
:focus-visible{
  outline: 3px solid var(--spot);
  outline-offset: 3px;
}


/* ==========================================================================
   4. THE SHEET, THE SKIP LINK, AND THE DESK
   ========================================================================== */

/* .jump: skip link. Hidden until focused, then an inked block top left.
   It is a real, readable 18px target, not a 1px sliver. */
.jump{
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  background: var(--ink);
  color: var(--paper);
  padding: .75rem 1rem;
  min-height: 48px;
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.jump:focus{
  left: 0;
  color: var(--paper);
}

/* .sheet: the single page wrapper. Header, main and footer all live inside
   it, so the measure and the gutter are declared exactly once. */
.sheet{
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
  background: var(--paper);
}

main{ display: block; }

/* Programmatic focus target for the skip link. Keeps the visible ring. */
main:focus-visible{
  outline: 3px solid var(--spot);
  outline-offset: 3px;
}

/* The desk. The only concession to a desktop viewport: one background and
   two borders. The sheet is defined by an ink edge (14.87:1 against the
   desk), never by a shadow and never by tone alone. Below 64em the sheet is
   full bleed and the desk never appears. */
@media (min-width: 64em){
  body{ background: var(--desk); }
  .sheet{
    background: var(--paper);
    border-left: 2px solid var(--ink);
    border-right: 2px solid var(--ink);
    min-height: 100vh;
  }
}


/* ==========================================================================
   5. RULES
   Three weights, and that is the entire structural vocabulary of this site.
   .rule--plate is the signature: 6px green with a 2px hairline 5px below it.
   It closes the masthead and opens the footer, so every page begins and ends
   with the same mark. That bookend is the identity and it costs two borders.
   ========================================================================== */

.rule--hair{
  border-bottom: 2px solid var(--rule-hair);
  margin-block: var(--s-3);
}

.rule--ink{
  border-bottom: 3px solid var(--rule-ink);
  margin-block: var(--s-5);
}

/* The 6px half of the signature. The 2px half is carried by whatever follows
   it (.directory under the plate, .caution in the footer) with a 5px
   margin-top, exactly as the masthead does it. Built from two real element
   borders rather than a pseudo-element on an <hr>, which some in-app
   browsers have historically handled badly. */
.rule--plate{
  border-bottom: 6px solid var(--rule-plate);
  margin-block: var(--s-6) 0;
}
/* Inside an article the same mark sits between the head and the prose, where
   72px of air would read as a break rather than as a rule. */
.entry__head + .rule--plate{ margin-top: var(--s-4); }


/* ==========================================================================
   6. MASTHEAD  ·  .plate
   A handbook cover block, flush LEFT and never centred. The wordmark is set
   as three explicit <span> lines so it can never overflow at 320px: the
   longest word, "Porchlight", measures about 231px against 280px of
   available width there.
   No "Established" line. That belongs to another property.
   ========================================================================== */

.plate{
  padding-block: var(--s-5) var(--s-3);
  border-bottom: 6px solid var(--rule-plate);
}

.plate__name{
  font-family: var(--face-plate);
  font-weight: 900;
  font-size: var(--t-plate);
  line-height: .92;
  letter-spacing: -.02em;
  color: var(--ink);
}
.plate__name span{ display: block; }

.plate__spec{
  margin-top: var(--s-3);
  max-width: 30rem;
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--spot);
}
.plate__spec .rule--hair{ margin-block: var(--s-2); }

/* The only layout on this site that changes at a breakpoint, and it degrades
   to plain stacked block flow, not to a broken grid. */
@media (min-width: 48em){
  .plate{
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: var(--s-4);
    flex-wrap: wrap;
  }
  .plate__spec{
    margin-top: 0;
    text-align: right;
  }
}


/* ==========================================================================
   7. NAVIGATION  ·  .directory
   An always visible row of text links. There is no hamburger at any width,
   and there must never be one: a menu this reader has to discover is a menu
   this reader does not use.
   At 320px the row wraps to three lines. That is correct behaviour, not a
   failure. The 2rem column gap separates horizontal neighbours and the 1rem
   row gap separates the wrapped lines: 16px of dead space between two 48px
   targets stacked one above the other, so a shaky tap on CAREGIVING cannot
   land on ABOUT. The column gap alone never covered that case.
   ========================================================================== */

.directory{
  border-top: 2px solid var(--rule-hair);
  border-bottom: 2px solid var(--rule-hair);
  margin-top: 5px;    /* completes the 6px + 2px signature under the plate */
}

.directory ul{
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.directory a{
  display: flex;
  align-items: center;
  min-height: 48px;
  padding-block: .75rem;
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* The current page keeps its underline. The amber ground and the 4px green
   edge are additive, never a replacement for the underline. */
.directory a[aria-current="page"]{
  background: var(--field);
  color: var(--spot-deep);
  padding-inline: .6rem;
  border-bottom: 4px solid var(--spot);
}


/* ==========================================================================
   8. FRONT PAGE  ·  .opening and .index
   The front page is a contents page, not an essay: a lead entry, then the
   printed index, then one amber band. No story grid, no tiles, no cards.
   ========================================================================== */

.opening{
  padding-block: var(--s-5) 0;
}

/* --- the printed index, with dotted leaders ------------------------------
   Built as a plain flex row. No display:contents, no transform, no repeating
   background gradient, no absolute positioning. The leader is a zero height
   flex child carrying a dotted bottom border, which is the plainest
   construction that produces leader dots. If flex ever fails entirely the
   row degrades to stacked inline elements that are all still readable and
   still tappable. Only the title is a link: there is no clickable card.   */

.index{
  list-style: none;
  margin: 0;
  padding: 0;
}

.index__head{
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--spot);
  margin: 0 0 var(--s-2);
  padding-bottom: var(--s-2);
  border-bottom: 3px solid var(--rule-ink);
}

.index__row{
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;   /* NOT baseline: a wrapped title would strand the
                              leader on the first line */
  column-gap: .5rem;
  padding-block: var(--s-3);
  border-top: 2px solid var(--rule-hair);
}
.index__row:first-child{ border-top: 0; }
.index__row:last-child{ border-bottom: 2px solid var(--rule-hair); }

.index__no{
  flex: 0 0 auto;
  font-family: var(--face-plate);
  font-weight: 700;
  font-size: var(--t-h3);
  line-height: 1.3;
  color: var(--spot);
  padding-bottom: .4rem;
}

.index__title{
  flex: 0 1 auto;
  display: inline-block;
  min-height: 48px;          /* touch target */
  padding-block: .4rem;
  font-family: var(--face-plate);
  font-weight: 700;
  font-size: var(--t-h3);
  line-height: 1.3;
}

.index__leader{
  flex: 1 1 2rem;
  min-width: 2rem;
  height: 0;
  border-bottom: 2px dotted var(--rule-hair);
  margin-bottom: .85rem;     /* lifts the dots onto the title baseline */
}

.index__label{
  flex: 0 0 auto;
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-quiet);
  padding-bottom: .55rem;
}

.index__gist{
  flex: 1 0 100%;            /* always its own line, at every width */
  margin-top: .35rem;
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--ink);
}


/* ==========================================================================
   9. ARTICLE PAGE  ·  .entry
   The numeral sits ABOVE the title, in flow, at every width. The step number
   and standing label sit ABOVE their h2, in flow, at every width. There is no
   margin rail and no grid: an earlier version of this design had one, and it
   was cut because it is the only thing that produces two visible columns, and
   this project has already been burned by fragile layout inside the Facebook
   in-app browser. The identity lives in the numbers and the labels, not in
   their position.
   ========================================================================== */

.entry{ padding-block: var(--s-5) 0; }

.entry__head{ margin-bottom: var(--s-4); }

/* The knockout tab. The one reversed element on the site: --paper on --spot,
   9.76:1. Square, inline-block, no radius, no shadow. */
.entry__label{
  display: inline-block;
  background: var(--spot);
  color: var(--paper);
  padding: .35rem .7rem;
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.entry__no{
  font-family: var(--face-plate);
  font-weight: 900;
  font-size: var(--t-numeral);
  line-height: .85;
  letter-spacing: -.02em;
  color: var(--spot);
  margin: var(--s-3) 0 var(--s-2);
}

.entry__title{
  font-family: var(--face-plate);
  font-weight: 900;
  font-size: var(--t-h1);
  line-height: 1.10;
  letter-spacing: -.015em;
  color: var(--ink);
  margin: 0 0 var(--s-3);
}

.entry__standfirst{
  font-size: var(--t-lead);
  line-height: 1.55;
  color: var(--ink);
  margin: 0 0 var(--s-3);
}

/* Exactly "Kept by Sophia Williams, North Carolina". No credential, ever.
   The words medical, nurse, clinical, professional, certified and specialist
   never appear next to her name. */
.entry__hand{
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-quiet);
}

/* --- prose scope ---------------------------------------------------------
   All prose typography is scoped here rather than set globally, so a legal
   page, a nav row or a label can never inherit article rhythm by accident. */

.entry__body{
  font-size: var(--t-body);
  line-height: 1.75;
  color: var(--ink);
}
/* When an article opens with the signature rule between the head and the
   prose, the body carries the 2px half of the mark. Written as an adjacent
   sibling so a page without the <hr> never shows a stray hairline. */
.rule--plate + .entry__body{
  border-top: 2px solid var(--rule-hair);
  margin-top: 5px;
  padding-top: var(--s-4);
}
.entry__body p{ margin: 0 0 1.15em; }
.entry__body ul,
.entry__body ol{ margin: 0 0 1.15em; padding-inline-start: 1.4em; }
.entry__body li + li{ margin-top: .6em; }
.entry__body h3{
  font-family: var(--face-plate);
  font-weight: 700;
  font-size: var(--t-h3);
  line-height: 1.3;
  margin: var(--s-4) 0 var(--s-2);
}
.entry__body strong,
.entry__body b{ font-weight: 700; }
.entry__body em{ font-style: italic; }
.entry__body > *:last-child{ margin-bottom: 0; }

/* .entry--plain: /about, /contact, /terms, /privacy-policy. Same body
   typography as an article, so the legal pages are exactly as readable as
   the writing. Suppresses the numeral and the questions panel. */
.entry--plain .entry__no,
.entry--plain .ask{ display: none; }

/* Long URLs in a privacy policy must never widen the page at 320px. */
.entry--plain .entry__body{ overflow-wrap: anywhere; }

/* --- numbered sections --------------------------------------------------
   An h2 every 250 to 350 words, three or four per article. If a section
   cannot be given a real standing label of two to four words, it is not a
   section: delete it. A numbered handbook invites listicle padding, and
   listicle padding is exactly what makes a page read as machine written. */

.step + .step{ margin-top: var(--s-6); }

.step__no{
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--spot);
  margin: 0;
}

.step__label{
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--spot);
  border-top: 2px solid var(--rule-hair);
  padding-top: var(--s-2);
  margin: var(--s-1) 0 var(--s-2);
}

/* Any h2 in prose, whether or not it carries a .step wrapper. The legal
   pages and /about run plain h2 sections with no step number, and they must
   look identical to an article heading.
   The 48px above the heading is load bearing on the long pages. /terms and
   /privacy-policy run fifteen to seventeen plain h2 sections, and with no top
   margin every one of them butts into the last line of the previous section:
   the page becomes an undifferentiated column of text for exactly the reader
   who needs the structure most. It also has to beat the 32px that .entry__body
   h3 already carries, or the hierarchy inverts and a subheading looks more
   separated than the section containing it. */
.entry__body h2,
.step h2{
  font-family: var(--face-plate);
  font-weight: 700;
  font-size: var(--t-h2);
  line-height: 1.20;
  letter-spacing: -.01em;
  color: var(--ink);
  margin: var(--s-5) 0 var(--s-3);
}
/* No leading gap when the prose opens on a heading. */
.entry__body > h2:first-child{ margin-top: 0; }
/* Inside a .step the standing label already carries the separation, and
   .step + .step carries 72px above that. Written after the rule above so the
   later of two equal specificities wins. */
.step h2{ margin-top: 0; }

/* The end mark. Pure CSS, no font dependency, no glyph that might not
   render in an in-app browser. */
.endmark{
  display: inline-block;
  width: .7em;
  height: .7em;
  background: var(--spot);
  margin-left: .35em;
  vertical-align: baseline;
}


/* ==========================================================================
   10. IN ARTICLE DEVICES
   ========================================================================== */

/* --- .field: the amber printed band --------------------------------------
   LOCKED RULES. It is a printed band, never a card:
     border-radius 0, no shadow, hairline bottom, 6px green top, and a
     negative inline margin exactly equal to the gutter so the tint bleeds
     into the gutter instead of floating inside it.
   Secondary text inside an amber band uses --ink, never --ink-quiet.       */
.field{
  background: var(--field);
  border-top: 6px solid var(--spot);
  border-bottom: 2px solid var(--rule-hair);
  margin-inline: calc(var(--gutter) * -1);
  padding: var(--s-4) var(--gutter);
  margin-block: var(--s-5);
}
.field p{
  color: var(--ink);
  margin: 0 0 1.15em;
}
.field > *:last-child{ margin-bottom: 0; }

.field__label{
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--spot);
  margin: 0 0 var(--s-2);
}

/* --- .aside-note: Sophia speaking directly -------------------------------
   Roman, not italic, and at full body size: italic sans at 21px is worse for
   a presbyopic eye, and shrinking an aside is how a reader loses it.       */
.aside-note{
  border-left: 4px solid var(--spot);
  padding-left: var(--s-3);
  margin-block: var(--s-4);
  font-size: var(--t-body);
  line-height: 1.75;
  color: var(--ink);
}
.aside-note p{ margin: 0 0 1.15em; }
.aside-note > *:last-child{ margin-bottom: 0; }

/* --- blockquote ----------------------------------------------------------
   BANNED AS A DEVICE. A pull quote in a health niche reads as a testimonial,
   and testimonials are prohibited on this property. This rule exists only so
   that a stray blockquote, if one ever lands here, renders as a quiet
   .aside-note rather than as decorative pulled type. Do not reach for it.  */
blockquote{
  border-left: 4px solid var(--spot);
  padding-left: var(--s-3);
  margin-block: var(--s-4);
  font-size: var(--t-body);
  font-style: normal;
  color: var(--ink);
}

/* --- .checklist ----------------------------------------------------------
   Boxes drawn in CSS, no icon font, no SVG, no emoji.
   It lists things to LOOK AT. It must never become a protocol, a regimen, or
   a list of things to take. */
.checklist{
  list-style: none;
  padding-inline-start: 0;
  margin: 0 0 1.15em;
}
.checklist li{
  position: relative;
  padding-left: 2.1em;
}
.checklist li + li{ margin-top: .6em; }
.checklist li::before{
  content: "";
  position: absolute;
  left: 0;
  top: .28em;
  width: 1.1em;
  height: 1.1em;
  border: 2px solid var(--spot);
}

/* --- .ask: questions to take to your doctor ------------------------------
   The recurring detail of this publication, at the foot of every article.
   Five ruled writing lines, built from five explicit block elements with a
   bottom border rather than a repeating gradient: five borders render
   identically in every engine ever shipped, survive @media print untouched,
   and cannot collapse, stripe wrongly or vanish under a background-image
   restriction. The gradient was the one fragile piece in this design.
   It sits on paper, never on the amber band, because the writing lines have
   to read as writing lines.
   It is also the compliance posture made into furniture: a publication whose
   recurring motif is a blank space reserved for the reader's OWN doctor is
   structurally hard to read as one trying to replace him. */
.ask{
  background: var(--paper);
  border-top: 3px solid var(--spot);
  border-bottom: 2px solid var(--rule-hair);
  padding-block: var(--s-4);
  margin-block: var(--s-6);
}
.ask__label{
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--spot);
  margin: 0 0 var(--s-2);
}
.ask__intro,
.ask__own{
  font-size: var(--t-body);
  color: var(--ink);
  margin: 0 0 var(--s-3);
}
.ask__list{
  margin: 0 0 var(--s-4);
  padding-inline-start: 1.4em;
  font-size: var(--t-body);
  color: var(--ink);
}
.ask__list li + li{ margin-top: .7em; }
.ask__line{
  height: 2.75rem;      /* 44px: room for an adult hand, including a shaky one */
  border-bottom: 2px solid var(--rule-hair);
}

/* --- .also: three underlined links, stacked ------------------------------
   No thumbnails, no cards, no summaries. Just the next thing to read. */
.also{
  margin-block: var(--s-5);
}
.also h2{
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--spot);
}
.also h2,
.also .field__label{ margin-bottom: var(--s-2); }
.also ul{
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 2px solid var(--rule-hair);
}
.also li{ border-bottom: 2px solid var(--rule-hair); }
.also a{
  display: flex;
  align-items: center;
  min-height: 48px;
  padding-block: .75rem;
  font-family: var(--face-plate);
  font-weight: 700;
  font-size: var(--t-h3);
  line-height: 1.3;
}


/* ==========================================================================
   11. FOOTER  ·  .caution and .colophon
   .caution carries the medical disclaimer and appears on EVERY page. It is
   deliberately not fine print: 19px in --ink on --field, 14.07:1. A reviewer
   should be able to read it without leaning in, and a reader should be able
   to read it without glasses.
   ========================================================================== */

.caution{
  background: var(--field);
  border-top: 2px solid var(--rule-hair);   /* the 2px half of the signature;
                                               the 6px half is the .rule--plate
                                               immediately above it */
  border-bottom: 2px solid var(--rule-hair);
  margin-inline: calc(var(--gutter) * -1);
  padding: var(--s-4) var(--gutter);
  margin-block: 5px 0;
  font-size: var(--t-note);
  line-height: 1.6;
  color: var(--ink);
}
.caution p{
  color: var(--ink);
  margin: 0 0 1.15em;
}
.caution > *:last-child{ margin-bottom: 0; }

.colophon{
  padding-block: var(--s-5) var(--s-6);
}

.colophon__wordmark{
  font-family: var(--face-plate);
  font-weight: 700;
  font-size: var(--t-h3);
  line-height: 1.3;
  color: var(--ink);
  margin: 0 0 var(--s-3);
}

/* Same row gap reasoning as .directory: these four wrap on a phone, and two
   48px targets stacked 4px apart is one tremor away from the wrong page. */
.colophon__links{
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  list-style: none;
  margin: 0 0 var(--s-3);
  padding: 0;
  border-top: 2px solid var(--rule-hair);
  border-bottom: 2px solid var(--rule-hair);
}
.colophon__links a{
  display: flex;
  align-items: center;
  min-height: 48px;
  padding-block: .75rem;
  font-size: var(--t-note);
}

.colophon__line{
  font-size: var(--t-note);
  line-height: 1.6;
  color: var(--ink-quiet);
  margin: 0 0 var(--s-2);
}

.colophon__type{
  font-family: var(--face-mark);
  font-size: var(--t-mark);
  font-weight: 500;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--ink-quiet);
  margin: 0;
}


/* ==========================================================================
   12. UTILITIES
   ========================================================================== */

.sr-only{
  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;
}


/* ==========================================================================
   13. FORCED COLOURS
   Windows high contrast and similar modes drop background colours. Anything
   whose meaning depends on a fill gets an explicit border in the system ink.
   ========================================================================== */

@media (forced-colors: active){
  .entry__label{ border: 2px solid CanvasText; }
  .field,
  .caution{ border: 2px solid CanvasText; }
  .ask__line{ border-bottom-color: CanvasText; }
  .index__leader{ border-bottom-color: CanvasText; }
  .checklist li::before{ border-color: CanvasText; }
}


/* ==========================================================================
   15. DESKTOP LAYOUT
   --------------------------------------------------------------------------
   Added after review: at 1600px the whole site was rendering as a 672px
   column centred in the viewport, because `--measure` (the READING measure)
   was being applied to `.sheet`, the page shell. Masthead, navigation and
   footer inherited it too, so a desktop browser got a phone layout with 460px
   of dead paper on each side.

   The rule this section enforces: the MEASURE constrains PROSE, never the
   PAGE. The shell is wide, the bands (masthead / nav / footer) span it, and
   only running text is held to a comfortable line length.

   Nothing here relaxes the legibility contract: body stays 22px, contrast
   stays AAA, links stay underlined, targets stay >=48px, nothing moves and
   there is still no hamburger. This is layout, not a redesign of the type.
   ========================================================================== */

:root{
  --shell: 76rem;      /* 1216px page shell */
  --rail:  20rem;      /* desktop sidebar */
}

/* The shell is wide from tablet up. Prose is constrained separately below. */
@media (min-width: 48em){
  .sheet{
    max-width: var(--shell);
    padding-inline: clamp(2rem, 5vw, 4rem);
  }
}

/* The "sheet on a desk" conceit is what made a wide screen read as a floating
   document rather than a site. Paper edge to edge instead. */
@media (min-width: 64em){
  body{ background: var(--paper); }
  .sheet{
    background: var(--paper);
    border-left: 0;
    border-right: 0;
    min-height: 0;
  }
}

/* ---- Masthead: nameplate and spec side by side, on one line ------------- */
@media (min-width: 48em){
  .plate{
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: end;
    column-gap: var(--s-5);
    padding-block: var(--s-6) var(--s-4);
  }
  /* The three <span>s exist so "Porchlight" can never overflow at 320px.
     There is no such risk here, so they run inline as one line. */
  .plate__name{
    font-size: clamp(3rem, 5.5vw, 4.5rem);
    line-height: 1;
    margin: 0;
  }
  .plate__name span{ display: inline; }
  .plate__name span + span::before{ content: " "; }

  .plate__spec{
    margin-top: 0;
    max-width: none;
    text-align: right;
    justify-self: end;
  }
  .plate__spec .rule--hair{ margin-inline-start: auto; width: 12rem; }
}

/* ---- Navigation: one row, never wrapping, spanning the shell ------------ */
@media (min-width: 48em){
  .directory ul{
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: clamp(1.25rem, 3.2vw, 3rem);
    overflow-x: auto;              /* defensive only; it does not wrap */
    scrollbar-width: none;
  }
  .directory ul::-webkit-scrollbar{ display: none; }
  .directory li{ flex: 0 0 auto; }
  .directory a{ white-space: nowrap; }
}

/* ---- Reading measure now belongs to the prose, not the page ------------- */
@media (min-width: 48em){
  .entry__standfirst,
  .entry__body > p,
  .entry__body > ul,
  .entry__body > ol,
  .entry__body > h2,
  .entry__body > h3,
  .entry__body > blockquote,
  .entry__body > .checklist,
  .entry__body > .step{
    max-width: var(--measure);
  }
  .entry__title{ max-width: 20ch; }
}

/* ---- Article spread: prose left, panels in a real sidebar --------------- */
@media (min-width: 64em){
  .entry{
    display: grid;
    grid-template-columns: minmax(0, calc(var(--measure) + 4rem)) minmax(16rem, var(--rail));
    column-gap: clamp(2.5rem, 5vw, 5rem);
    align-items: start;
  }
  /* Column 1 is the DEFAULT for every child. Only the explicit allowlist
     below moves to the sidebar. Without this, any child the template adds
     later (the shop's product list, for instance) silently lands in the
     narrow column and the page looks broken. */
  .entry > *{ grid-column: 1; }
  .entry__head{ grid-column: 1 / -1; }

  /* The sidebar: side matter only, never running prose. */
  .entry > .ask,
  .entry > .also,
  .entry > .alongside{
    grid-column: 2;
    grid-row: auto;
    margin-block: 0 var(--s-5);
  }
  .entry > .ask{ position: sticky; top: var(--s-4); }

  /* Full-bleed inside the spread: anything that is a listing, not prose. */
  .entry > .goods,
  .entry > .goods__head{ grid-column: 1 / -1; }
}

/* ---- Front page: a real front page -------------------------------------
   The opening letter and the "what this is" panel share the top band, then
   the contents runs the full width in two columns underneath. Scoped with
   :has() so it only applies to the page that actually has an opening letter;
   a browser without :has() simply keeps the stacked layout, which still
   reads correctly. */
@media (min-width: 64em){
  main:has(> .opening){
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(17rem, 21rem);
    column-gap: clamp(2.5rem, 5vw, 5rem);
    align-items: start;
  }
  main:has(> .opening) > .entry.opening{ grid-column: 1; grid-row: 1; }
  main:has(> .opening) > .field{
    grid-column: 2;
    grid-row: 1;
    position: sticky;
    top: var(--s-4);
    margin-block: 0;
  }
  main:has(> .opening) > hr.rule--ink{ grid-column: 1 / -1; grid-row: 2; }
  main:has(> .opening) > section{ grid-column: 1 / -1; grid-row: 3; }

  /* The opening letter is prose: it must not inherit the article sidebar grid. */
  .entry.opening{ display: block; }

  .index{
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(2rem, 4vw, 4.5rem);
    border-top: 2px solid var(--rule-hair);
  }
  .index__row{ border-top: 0; border-bottom: 2px solid var(--rule-hair); }
}

/* ---- Footer: a real band, not a stack ---------------------------------- */
@media (min-width: 48em){
  .colophon{
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: var(--s-5);
    row-gap: var(--s-3);
    padding-block: var(--s-5) var(--s-6);
  }
  .colophon__wordmark{ grid-column: 1; margin: 0; }
  .colophon__links{
    grid-column: 2;
    grid-row: 1;
    flex-wrap: nowrap;
    border: 0;
    margin: 0;
    justify-content: flex-end;
  }
  .colophon__line{ grid-column: 1; margin: 0; }
  .colophon__type{ grid-column: 2; justify-self: end; margin: 0; }
}

/* The full-bleed panels were bled against the phone gutter. Keep them tied to
   whatever the current gutter actually is. */
@media (min-width: 48em){
  .caution,
  .field{
    margin-inline: 0;
    padding-inline: var(--s-4);
  }
}


/* ==========================================================================
   14. PRINT
   A real block, not an afterthought. This reader prints an article and hands
   it to a doctor, so the sheet that comes out of a cheap inkjet has to work:
   black on white, 12pt body, no amber fills, no reversed tab smear, the
   questions panel intact with usable writing lines, and the medical
   disclaimer surviving onto the page.
   ========================================================================== */

@page{ margin: 18mm; }

@media print{
  :root{
    --paper: #fff; --field: #fff; --desk: #fff;
    --ink: #000; --ink-quiet: #000;
    --spot: #000; --spot-deep: #000; --visited: #000;
    --rule-hair: #666; --rule-ink: #000; --rule-plate: #000;
  }

  body{
    background: #fff;
    color: #000;
  }

  .sheet{
    max-width: none;
    border: 0;
    padding: 0;
    background: #fff;
  }

  body,
  .entry__body p,
  .entry__body li,
  .ask__intro,
  .ask__own,
  .ask__list{ font-size: 12pt; line-height: 1.5; }

  .entry__standfirst{ font-size: 13pt; }
  .entry__title{ font-size: 22pt; }
  .entry__no{ font-size: 26pt; }
  .entry__body h2,
  .step h2{ font-size: 15pt; }
  /* The 48px the screen puts above a heading is paper the reader pays for.
     14pt still separates the sections plainly on the sheet handed to a doctor. */
  .entry__body h2{ margin-top: 14pt; }
  .step h2{ margin-top: 0; }
  .plate__name{ font-size: 20pt; }
  .caution{ font-size: 10pt; }

  /* screen furniture that must not print */
  .jump,
  .directory,
  .index,
  .also,
  .colophon__type{ display: none !important; }

  /* the knockout tab would print as a black smear */
  .entry__label{
    background: #fff !important;
    color: #000 !important;
    border: 2px solid #000;
    padding: .2rem .5rem;
  }

  /* the amber bands become outlined, not filled */
  .field,
  .caution{
    background: #fff !important;
    border: 2px solid #000;
    margin-inline: 0;
    padding: 10pt;
  }

  /* the disclaimer MUST survive onto the sheet handed to the doctor */
  .caution{
    display: block !important;
    break-inside: avoid;
  }

  /* the questions panel must arrive intact, with usable lines */
  .ask{ break-inside: avoid; }
  .ask__line{ border-bottom: 1pt solid #000; }

  h1, h2, h3,
  .step__label{ break-after: avoid; }
  p, li{ orphans: 3; widows: 3; }

  /* expand link destinations, since paper cannot be clicked */
  .entry__body a[href^="http"]::after,
  .entry__body a[href^="/"]::after{
    content: " (" attr(href) ")";
    font-size: 10pt;
  }

  /* traceability: a printed page handed to a doctor can be traced back */
  .colophon__line::after{
    content: " · Printed from theporchlightjournal.com";
  }
}
