/* SKIN: education (college consulting, admissions advising, tutoring, academic coaching)
   Feel: editorial and unhurried — a good book, not a brochure. Warm off-white
   paper, dark-purple ink, ONE orange accent doing all the pointing.

   Built 2026-08-27 for studio-sb-coaching (10th vertical). Two things make this
   vertical different from `professional`, and both are why it needed its own file:
     1. The paper is WARM off-white, not white on cool grey. professional.css is
        #ffffff over #f4f6f9 (a blue-grey), which fights an orange/purple brand.
     2. This vertical PUBLISHES LONG-FORM WRITING. Every other skin dresses up
        short service blurbs; a college-essay practice puts 700-word student
        essays on the page, so a real reading column is a first-class need here
        (.prose below), not decoration.

   Deliberately does NOT override .btn. base.css gives buttons a 2px --dark
   border, which reads as crisp/editorial against warm paper and is worth
   keeping. The one button change needed (orange fill with no contrasting
   outline) is done at TOKEN level via --accent-border, which base.css already
   reads in BOTH .btn-accent and .mobile-nav a.mobile-cta. That avoids the
   laundry-skin bug entirely: a skin restyling .btn beats base.css's own
   .btn-accent/.btn-primary at equal (0,1,0) specificity because the skin loads
   later, so it must restate every variant. Not touching .btn = nothing to
   restate. See site-factory/CLAUDE.md Log, 2026-08-25. */
:root{
  --paper:#FBF8F3;                    /* warm off-white */
  --ink:#2B1B3D;                      /* 14.94:1 on paper */
  --muted:#5C5266;                    /* 6.95:1 on paper, 6.34:1 on --section-bg-alt */
  --radius:10px;
  --shadow:0 2px 14px rgba(43,27,61,.07);
  --tile-border:1px solid #E7DED1;    /* warm hairline, not grey */
  --header-line:1px solid #E7DED1;
  --section-bg-alt:#F4EDE4;

  /* Orange fill, no contrasting outline. base.css reads this in .btn-accent AND
     the mobile menu's CTA, so both change from one token and neither rule is
     forked. Accent #F0894A + --dark text measures 6.32:1 (AA at any size). */
  --accent-border:var(--accent);

  /* Heavier than the base overlay ON PURPOSE. Every other skin sits over a
     photograph that is already mid-to-dark; this brand's images are black line
     art on near-white, so the default .62 overlay leaves a washed-out grey
     field with low-contrast white text over it. At these values the artwork
     reads as pale purple linework on a deep purple ground — still visibly an
     image (the fleet rule is no flat-color heroes), with white text sitting
     comfortably clear of it. Tuned against real renders, not guessed. */
  --hero-overlay:linear-gradient(180deg,rgba(43,27,61,.86),rgba(43,27,61,.68) 48%,rgba(43,27,61,.9));
}

/* Display face here is a high-contrast serif. base.css tightens all headings by
   -.015em, which is right for a grotesk and closes up a didone's thin strokes —
   so tracking goes back to near-normal. Equal specificity, skin loads later. */
h1,h2,h3{letter-spacing:-.004em}
/* Sized so this vertical's hero headlines hold ONE line across the desktop
   range. Measured, not guessed: the .wrap content column caps at 1096px, and
   the longest headline on the site ("Essays that sound like the student who
   wrote them", 49 chars) breaks to two lines above 47.5px. The cap is 2.85rem
   (45.6px), leaving ~4% headroom for font-metric variation between machines,
   and the vw term is 3.9 so the same holds at 1100px and below rather than only
   at full width. Below ~840px the 2.05rem floor takes over and headlines wrap,
   which is correct on a phone. */
h1{font-size:clamp(2.05rem,3.9vw,2.85rem)}
.hero{min-height:68vh}
.tile h3{color:var(--primary)}
.eyebrow{color:var(--primary)}          /* 10.23:1 on paper, 9.33:1 on --section-bg-alt */

/* MEASURED FIX, not a preference. base.css colors the hero eyebrow
   var(--accent), which is right over a photograph. Over THIS vertical's
   near-white line art it is not: composited against the overlay at the
   eyebrow's real position, accent #F0894A measures 2.61:1, and 2.21:1 at the
   hero's brightest point — nowhere near the 4.5:1 that AA wants for 12.8px
   text. The text-shadow base.css adds is a perceptual safety net; it does not
   move a measured ratio.
   Darkening the overlay until the accent passes needs alpha >= 0.88, and at
   that point the artwork's own line-vs-ground contrast collapses from 3.01:1
   to 1.47:1 — the illustration becomes the flat-color hero the fleet rule
   forbids. So the TEXT gives way, not the image: a warm off-white drawn from
   this palette rather than plain white, measured 4.88:1 at the BRIGHTEST point
   anywhere in the hero (worst case = compositing over pure white, which is
   what every illustration in this vertical grounds to).
   Same class of bug as yossefs-laffa-milia's warm-accent-over-warm-photo
   finding; opposite resolution, because here the backdrop is what needs
   protecting. */
.hero .eyebrow{color:#F7EFE8}

/* ---------- nav width ----------
   Two things compete for the header bar here: a multi-item nav and (on the
   sites that use one) a wordmark lockup that is ~165px wider than a bare logo.
   Measured: with the wordmark showing, brand+nav+phone+CTA needs ~953px, which
   overflows the 862px case the fleet cares about (a Windows laptop at 150%
   scaling). Dropping the mini phone link below 990px brings it to ~809px and it
   fits. The phone is still in the mobile menu, the footer, and every page CTA.
   The laundry skin hit the same wall from the other direction (five nav items,
   no wordmark) and took the same two measures.
   Base rules first, media queries after (the CSS ordering trap). */
.main-nav a,.nav-item > a{white-space:nowrap}

/* This vertical's primary CTA is "Schedule a Conversation" — 23 characters,
   against the fleet default's 16. Measured: without nowrap it wraps to two lines
   anywhere under ~1080px and the header grows from 78px to 103px, which reads as
   a broken header rather than a long label. Scoped to this skin rather than
   base.css because forcing nowrap on every fleet CTA is a real rendered change
   on 17 live sites for a problem only this one has. */
.hdr-cta .btn{white-space:nowrap}

/* Measured widths with the wordmark lockup, a 4-item nav and a nowrap CTA:
   lockup + phone + button needs ~1069px, so the mini phone link stands down
   below 1080 rather than the fleet's 860. It is still in the mobile menu, the
   footer, and on the contact page. */
@media (max-width:1080px){.tel-mini{display:none}}

/* ---------- <select> in the lead form ----------
   base.css styles input + textarea and has never had a select to style, because
   until now no vertical asked a multiple-choice question. This one asks "what
   kind of help are you looking for?", and an unstyled native select next to
   three styled inputs makes the whole form look half-finished. Values are copied
   from base.css's own .lead-form input rule so they cannot drift apart, plus the
   appearance reset and custom caret a native select needs. The 16px floor at
   560px mirrors base.css's iOS-zoom guard. */
.lead-form select{font-family:var(--body);font-size:.95rem;padding:.72rem .8rem;
  border:1.5px solid #c9c9c4;border-radius:8px;background-color:#fff;color:var(--ink);
  appearance:none;-webkit-appearance:none;padding-right:2.4rem;
  background-image:linear-gradient(45deg,transparent 50%,var(--primary) 50%),
                   linear-gradient(135deg,var(--primary) 50%,transparent 50%);
  background-position:calc(100% - 18px) 1.18rem,calc(100% - 13px) 1.18rem;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.lead-form select:focus{outline:3px solid var(--primary);outline-offset:0}
@media (max-width:560px){.lead-form select{font-size:16px;padding:.8rem .85rem;padding-right:2.4rem}}

/* ---------- ONE VERTICAL RHYTHM ----------
   Measured on a real page before writing this, because the spacing was not
   merely uneven, it was three different bugs wearing the same coat:
     heading -> text ran 0px / 16px / 61px / 88px across six sections,
     paragraph -> paragraph was 0px, and description -> buttons was 0px.
   Causes: base.css resets ALL margins to 0, so `h1` has none; `.sub` carries no
   margin at all, so consecutive paragraphs and a following button row simply
   touch; and `.cta-row` is only styled INSIDE .hero, so elsewhere it had
   neither gap nor top margin. The 61px and 88px were not margins at all — they
   were `.split`'s align-items:center pushing a short text column down against a
   taller image, which is why the gap differed per section.
   Fixed here as four numbers, applied everywhere:
     heading -> body 1rem · body -> body 1rem · body -> buttons 1.8rem
     (the value the hero already used) · heading -> a grid/photo row 2.3rem. */
h1{margin-bottom:1rem}
.sub{margin-bottom:1rem}
.sub:last-child{margin-bottom:0}
/* base.css styles .cta-row only under .hero; outside it the buttons had no gap
   and no separation from the text above them. `.hero .cta-row` (0,2,0) still
   wins inside the hero, and it already uses this same 1.8rem. */
.cta-row{display:flex;flex-wrap:wrap;gap:14px;margin-top:1.8rem}

/* ---------- long-form reading column ----------
   The reason this skin exists. .sub is a 58ch muted intro lede; a student essay
   is body copy and needs full ink, a longer measure and looser leading. */
.prose{max-width:66ch;color:var(--ink);font-size:1.02rem;line-height:1.78}
.prose p{margin-bottom:1.05rem}
.prose p:last-child{margin-bottom:0}
.prose > h3{margin:1.8rem 0 .6rem;font-size:1.1rem}
.prose blockquote{margin:1.4rem 0;padding:.2rem 0 .2rem 1.2rem;
  border-left:3px solid var(--accent);color:var(--muted);font-style:italic}

/* Attribution under a testimonial. Beats .faq p (0,1,1) at (0,2,0). */
.attrib{display:block;margin-top:.75rem;font-weight:600;font-size:.9rem;color:var(--primary)}
.faq .attrib{color:var(--primary)}

/* ---------- two-up grid ----------
   base.css ships .grid3 only. Half this site's content comes in pairs (two
   workshops, two books, planning-ahead vs application-season), and forcing
   pairs through a 3-column grid leaves a hole in every row. */
.grid2{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;margin-top:2.3rem}
@media (max-width:720px){.grid2{grid-template-columns:1fr}}

/* A .split whose image is a book or box COVER rather than a square illustration.
   --photo-ratio is per-SITE and single-valued, so a site whose illustrations are
   1/1 crops a 2:3 cover by 33% of its height under object-fit:cover — measured on
   a real render, and on a cover the third you lose is the title. This overrides
   the ratio for that one slot instead of accepting the crop, which is the fleet's
   "match the box to the SOURCE" rule applied to a second source shape on one
   site. (0,2,1) beats .split img's (0,1,1). */
.split.has-cover img{aspect-ratio:2/3;object-fit:contain;max-width:130px;
  justify-self:center;border-radius:4px;box-shadow:0 3px 12px rgba(43,27,61,.16)}

/* Same idea, other source shapes. --photo-ratio is ONE value per site (1/1
   here, matching the brand illustrations), so any page carrying a second or
   third source shape needs its own box or it gets cropped against itself.
   3/2 = landscape photography, 3/4 = portrait product shots; both match their
   sources exactly, so object-fit:cover removes nothing. */
.split.has-wide img{aspect-ratio:3/2;max-width:460px}
.split.has-portrait img{aspect-ratio:3/4;max-width:330px}

/* Artwork with its background knocked out. It must NOT get .split img's card
   treatment — a rounded corner and a drop shadow on a transparent cutout draws
   a box around empty space. aspect-ratio:auto hands the ratio back to the file,
   so the art is never squeezed against this site's 1/1 --photo-ratio. */
.split img.cutout{aspect-ratio:auto;max-width:250px;object-fit:contain;
  border-radius:0;box-shadow:none;background:none}

/* Image on the LEFT. base.css's .split is 1.1fr .9fr and gives the first child
   the wider column, so a media-first markup order needs the ratio reversed or
   the picture gets more room than the words. Below 860px base.css collapses to
   one column and the art simply sits above the heading. */
.split.media-left{grid-template-columns:.8fr 1.2fr}
/* This override is REQUIRED, not belt-and-braces. base.css collapses .split to
   one column on phones with `.split{grid-template-columns:1fr}` inside a media
   query — but that selector is (0,1,0) and `.split.media-left` is (0,2,0), so
   the two-column rule kept winning and the artwork was crushed into a 115px
   column beside the text at 375px (measured). Specificity beats media queries;
   a modifier on a base component has to restate the base's own breakpoint. */
@media (max-width:860px){.split.media-left{grid-template-columns:1fr}}

/* ---------- artwork floated in the hero ----------
   This skin's hero overlay is deliberately heavy (.86 at the top) because the
   vertical's imagery is near-white line art. That is right for a backdrop and
   wrong for a product: a box cover behind that overlay goes muddy purple. So
   the artwork sits IN FRONT of the shade as a second grid column, at full
   saturation, against the darkened photo behind it — which is what makes the
   panel read as vibrant rather than washed.
   base.css already collapses .hero-grid.has-form to one column at 920px; this
   mirrors that breakpoint so the art drops under the text on narrow screens
   rather than squeezing the headline. */
.hero-grid.has-art{grid-template-columns:1.12fr .88fr;gap:2.4rem}
@media (max-width:920px){.hero-grid.has-art{grid-template-columns:1fr}}
.hero-art{width:100%;max-width:280px;height:auto;aspect-ratio:2/3;object-fit:contain;
  justify-self:center;border-radius:10px;
  box-shadow:0 20px 48px rgba(0,0,0,.45),0 3px 10px rgba(0,0,0,.3)}
@media (max-width:920px){.hero-art{max-width:210px}}

/* ---------- product photo row ----------
   For real photographs OF a physical product, as opposed to the .covers strip
   (flat cover artwork at thumbnail size). Deliberately bigger than .covers,
   because here the photograph IS the content — the job is showing someone what
   is actually in the box. */
.shots{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:2.3rem;list-style:none}
.shots li{margin:0}
.shots figure{margin:0}
.shots img{width:100%;height:auto;aspect-ratio:3/4;object-fit:cover;
  border-radius:var(--radius);box-shadow:0 4px 18px rgba(43,27,61,.16)}
.shots figcaption{margin-top:.6rem;font-size:.86rem;color:var(--muted)}
@media (max-width:720px){.shots{grid-template-columns:repeat(2,1fr);gap:14px}}
@media (max-width:460px){.shots{grid-template-columns:1fr;max-width:300px}}

/* ---------- product cover strip ----------
   Book covers are 2:3 and must NEVER be cropped — a cover with its title cut off
   is worse than no cover. So they get their own box rather than going through
   .split, which is pinned to --photo-ratio (1/1 on this site, matching the brand
   illustrations and the portrait of Sofia). This is the same principle as the
   fleet's "match the box to the SOURCE" rule, applied to a second source shape
   on one site. object-fit:contain rather than cover so a future cover that is
   not exactly 2:3 letterboxes instead of losing its title. */
/* The grid is capped too, not just the image: a 110px cover centered in a 348px
   cell reads as an accident rather than a decision. Narrowing the whole strip
   keeps each cover close to its own caption. */
.covers{display:grid;grid-template-columns:repeat(3,1fr);gap:28px;margin-top:2.1rem;
  list-style:none;max-width:720px}
.covers.two{grid-template-columns:repeat(2,1fr);max-width:480px}
.covers figure{margin:0}
/* A cover here is a REFERENCE, not the subject of the page — the caption below
   carries the title in bold, so nothing depends on reading the artwork. Sized
   accordingly and centered with margin auto. */
.covers img{width:100%;max-width:110px;margin:0 auto;height:auto;aspect-ratio:2/3;
  object-fit:contain;border-radius:4px;box-shadow:0 3px 12px rgba(43,27,61,.16)}
/* Column flex so the caption's three parts — title, description, button — each
   get their own line. base.css makes .btn `display:inline-flex`, so left in
   normal flow it runs on as part of the sentence and wraps beside the last few
   words ("…feels impossible. [Learn more]"), which reads as a mistake.
   A flex container wraps the loose text node into an anonymous item, so this
   works without adding a wrapper element to the markup — which means every
   cover caption on every page gets it, with no page file touched.
   align-items stays at its default `stretch` so the description still fills the
   column and wraps normally; only the BUTTON gets align-self:flex-start, so it
   shrinks to its label instead of spanning the whole column. */
.covers figcaption{display:flex;flex-direction:column;
  margin-top:.7rem;font-size:.9rem;color:var(--muted)}
.covers figcaption b{display:block;font-family:var(--display);font-weight:800;
  font-size:.98rem;color:var(--ink);margin-bottom:.25rem}
.covers .btn{align-self:flex-start;margin-top:.7rem}
@media (max-width:720px){.covers,.covers.two{grid-template-columns:repeat(2,1fr);gap:20px;max-width:none}
  .covers img{max-width:100px}}
@media (max-width:460px){.covers,.covers.two{grid-template-columns:1fr;max-width:300px}
  .covers img{max-width:92px}}

/* ---------- stat band ---------- */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:2.2rem;list-style:none}
.stats li{text-align:center;padding:1.15rem .8rem;background:#fff;
  border:var(--tile-border);border-radius:var(--radius)}
.stats b{display:block;font-family:var(--display);font-weight:800;font-size:1.45rem;
  color:var(--primary);line-height:1.15}
.stats span{display:block;font-size:.84rem;color:var(--muted);margin-top:.3rem}
@media (max-width:720px){.stats{grid-template-columns:repeat(2,1fr)}}

/* ---------- chips (concrete nouns: places, stages, topics) ---------- */
.chips{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.3rem;list-style:none}
.chips li{font-size:.86rem;font-weight:600;padding:.42rem .85rem;border-radius:999px;
  background:#fff;border:var(--tile-border);color:var(--ink)}

/* ---------- sequence flow (The Runway stages) ----------
   Arrow is absolutely positioned so it sits in the gutter BETWEEN boxes rather
   than inside the last one's border. Hidden once the row wraps to one item per
   line, where a trailing arrow would point at nothing. */
.flow{display:flex;flex-wrap:wrap;gap:.55rem 1.9rem;margin-top:1.4rem;list-style:none}
.flow li{position:relative;font-family:var(--display);font-weight:700;font-size:.93rem;
  padding:.5rem .9rem;background:#fff;border:var(--tile-border);border-radius:var(--radius)}
.flow li:not(:last-child)::after{content:"\2192";position:absolute;right:-1.35rem;
  top:50%;transform:translateY(-50%);color:var(--accent);font-weight:800}
@media (max-width:620px){.flow{gap:.5rem}.flow li:not(:last-child)::after{display:none}}

/* ---------- in-page anchor clearance ---------- ADDED 2026-10-01
   .site-header is position:fixed, so a jump link lands its target UNDERNEATH
   the header: the heading you were sent to is invisible and the page looks
   like it scrolled to the wrong place. base.css has no scroll-margin anywhere
   and solves the same problem once, by hand, with .post-hero's 7.2rem top
   padding (see the comment there — it was found by measuring, not by reading).
   This vertical navigates WITHIN pages (a service page with three sections and
   buttons that jump to them, an essay collection linked from a hero), so it
   needs the general fix. The header measures 78px here and 65px below 860px;
   96px/84px leave a little air above the heading.
   Only `section[id]` and `details[id]` are targeted, so this cannot affect any
   element that merely happens to carry an id. */
section[id],details[id]{scroll-margin-top:96px}
@media (max-width:860px){section[id],details[id]{scroll-margin-top:84px}}

/* ---------- .split with a narrower media column ---------- ADDED 2026-10-01
   base.css's .split is 1.1fr .9fr, which suits a photo that carries real
   weight. It is wrong for a section whose text column has to hold a bullet
   list and a button row as well as a paragraph: at 1096px of content that
   leaves 579px of text, the two buttons total 565px + a 14px gap, and they
   wrap onto two rows a hair short of fitting. Giving the artwork less room
   fixes that and shrinks the illustration, which is what the operator asked
   for ("move the image more right or make it smaller").
   Measured at 1440: text column 579 -> 710px, artwork 420 -> 342px, buttons
   back to one row, and the two-column .ticks list stops wrapping.

   THE BREAKPOINT IS RESTATED ON PURPOSE. .split.media-narrow is (0,2,0) and
   base.css's mobile collapse @media{.split{grid-template-columns:1fr}} is
   (0,1,0) - specificity beats media queries, so without the second rule this
   modifier keeps its two columns all the way down to 375px and crushes the
   artwork into a sliver. That exact bug shipped once already with
   .split.media-left; see site-factory/CLAUDE.md. */
.split.media-narrow{grid-template-columns:1.35fr .65fr}
@media (max-width:860px){.split.media-narrow{grid-template-columns:1fr}}
