/* The Dryer Edit - shared design system v2
   Built 2026-09-18 after a two-round design debate with DeepSeek.
   SINGLE SOURCE OF TRUTH. No page should carry its own <style> block.

   TYPOGRAPHY JOB RULE (this is the rule, not decoration):
     SERIF (Georgia)  = our editorial voice - headings, the verdict sentence, the logo.
     SANS  (system)   = everything factual or functional - body copy, tables, specs,
                        provenance, nav, buttons.
   If a serif appears anywhere that is not our own judgement speaking, it is a bug.
*/

/* ---------- TOKENS ---------- */
:root{
  --ink:#1c1917;        /* body text            17.5:1 on white */
  --mut:#57534e;        /* secondary text        7.6:1 */
  --prov:#6b6560;       /* provenance/date/source lines
                           5.74:1 on white, 5.50 on wash, 5.16 on badge - passes AA on all three.
                           Replaces #a8a29e (2.52:1) and #777 (4.48:1), both of which FAILED AA
                           while carrying our sourcing lines, the most trust-critical text we have. */
  --o:#b45309;          /* accent                5.0:1 */
  --o-dk:#92400e;
  --line:#e7e5e4;
  --bg:#fff;
  --wash:#fafaf9;
  --badge:#fef3c7;
  --good:#166534;
  --bad:#9a3412;

  --measure:68ch;       /* prose line length target. Stated in ch, not px, so it stays correct
                           if the type scale changes. */
  --shell:900px;
  --radius:10px;
}

/* legacy aliases - the site had THREE vocabularies for one palette
   (--o/--mut, --accent/--muted/--accentdark, --accent/--accent2/--card).
   These keep old markup rendering while pages migrate. Delete once all 15 are on site.css. */
:root{
  --accent:var(--o); --accent2:var(--o-dk); --accentdark:var(--o-dk);
  --muted:var(--mut); --soft:var(--wash); --card:var(--wash);
  --warn:var(--bad);
}

*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  font-family:Inter,system-ui,-apple-system,"Segoe UI",sans-serif;
  color:var(--ink); background:var(--bg); margin:0;
  font-size:17px; line-height:1.65;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4,.logo,.verdict-line{
  font-family:Georgia,"Times New Roman",serif;
  letter-spacing:-.01em;
}
a{color:var(--o)}
img{max-width:100%;height:auto}

/* ---------- SHELL ---------- */
/* Sticky header. Cheap and correct; NOT claimed as strategy - at current traffic it moves
   no metric. It is here because the brand name scrolling away is wrong on a site whose
   whole social plan is being remembered by name. */
header{
  position:sticky; top:0; z-index:20;
  background:rgba(255,255,255,.94); backdrop-filter:blur(8px);
  border-bottom:1px solid var(--line);
  padding:14px 20px;
}
header .inner,.hdr-inner{
  max-width:var(--shell); margin:0 auto;
  display:flex; justify-content:space-between; align-items:center; gap:16px;
}
header .logo{
  color:var(--ink); font-weight:700; font-size:1.22rem;
  letter-spacing:.02em; text-decoration:none; white-space:nowrap;
}
header nav a{
  font-family:Inter,system-ui,sans-serif;   /* chrome is sans, per the job rule */
  color:var(--mut); text-decoration:none; margin-left:18px; font-size:.9rem;
}
header nav a:hover{color:var(--o)}

.hero{max-width:var(--shell);margin:0 auto;padding:40px 20px 4px}
.hero h1{font-size:2.15rem;line-height:1.18;margin:0 0 12px;max-width:26ch}
.hero p{color:var(--mut);font-size:1.1rem;margin:0;max-width:60ch}

main{max-width:820px;margin:0 auto;padding:8px 20px 80px}
/* prose measure applies to running text only, so tables and grids keep their room */
main p,main li{max-width:var(--measure)}

footer{
  max-width:var(--shell);margin:0 auto;padding:24px 20px 44px;
  border-top:1px solid var(--line);color:var(--prov);font-size:.84rem;
}
footer p{max-width:var(--measure)}

/* ---------- DISCLOSURE ---------- */
/* Always above the first CTA. Never restyled to be less visible. */
/* TWO class names exist in the wild for this block - .disc and .disclosure. Six pages use
   .disclosure, including best-hair-dryer-under-60, which carries most of our measured clicks.
   Styling only .disc would have shipped the FTC disclosure as unstyled plain text on those
   pages. Both names are bound here, permanently. */
.disc,.disclosure{
  background:var(--wash);border:1px solid var(--line);border-radius:8px;
  padding:11px 15px;font-size:.87rem;color:var(--mut);margin:18px 0;
  max-width:var(--measure);
}

/* ---------- VERDICT BLOCK ---------- */
/* Order inside is deliberate and was the main outcome of the debate:
   verdict -> who should NOT buy -> CTA.
   The CTA sits at the END, separated from the disclosure by the negative line. Putting the
   CTA directly under the disclosure turns a review into an affiliate landing page. */
.verdict{
  border:1px solid var(--line); border-left:5px solid var(--o);
  border-radius:var(--radius); background:var(--bg);
  box-shadow:0 2px 14px rgba(28,25,23,.05);
  padding:22px 24px; margin:18px 0 26px;
}
.verdict .badge{
  display:inline-block;background:var(--badge);color:var(--o-dk);
  font-family:Inter,system-ui,sans-serif;
  font-weight:700;font-size:.76rem;letter-spacing:.03em;text-transform:uppercase;
  padding:4px 12px;border-radius:20px;
}
.verdict h2,.verdict .verdict-line{
  font-size:1.42rem;line-height:1.3;margin:12px 0 6px;max-width:34ch;
}
.verdict .specs{
  font-family:Inter,system-ui,sans-serif;
  color:var(--mut);font-size:.94rem;margin:8px 0;max-width:var(--measure);
}
.verdict p{max-width:var(--measure)}
/* the honest negative, given real weight rather than buried */
.verdict .notfor{
  border-top:1px solid var(--line);margin:16px 0 0;padding:14px 0 4px;
  color:var(--mut);font-size:.96rem;max-width:var(--measure);
}
.verdict .notfor b{color:var(--ink)}

/* ---------- CTA ---------- */
.cta{
  display:inline-block;background:var(--o);color:#fff !important;
  font-family:Inter,system-ui,sans-serif;font-weight:700;font-size:1rem;
  padding:14px 28px;border-radius:8px;text-decoration:none;margin:14px 0 4px;
  transition:background .15s ease;
}
.cta:hover{background:var(--o-dk)}
.cta:focus-visible{outline:3px solid var(--o-dk);outline-offset:3px}
.cta + .small,.cta + .prov{display:block;margin-top:8px}

/* provenance / source / date - the trust lines. Sans, per the job rule: these are facts. */
.small,.prov,figcaption{
  font-family:Inter,system-ui,sans-serif;
  color:var(--prov);font-size:.82rem;line-height:1.55;max-width:var(--measure);
}

/* ---------- SECTIONS, TABLES, PROS AND CONS ---------- */
h2.section,main h2{font-size:1.42rem;margin:40px 0 10px;max-width:30ch}
main h3{font-size:1.12rem;margin:26px 0 6px;max-width:34ch}

table{width:100%;border-collapse:collapse;margin:16px 0;font-size:.93rem}
th,td{border:1px solid var(--line);padding:10px 11px;text-align:left;vertical-align:top}
th{background:var(--wash);font-weight:600}
tbody tr:nth-child(even) td{background:#fcfcfb}

.cols{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin:14px 0}
.cols ul{margin:6px 0;padding-left:18px}
.pro li{color:var(--good)}
.con li{color:var(--bad)}
.who{
  background:var(--wash);border:1px solid var(--line);border-radius:12px;
  padding:16px 20px;margin:14px 0;
}

/* ---------- CARD HIERARCHY ---------- */
/* Replaces 11 visually identical grey boxes. Two tiers now:
   .card-major for the pages that carry commercial weight, .card-min for guides.
   Identical boxes in a long row is the visual signature of a content farm, and it was
   the single clearest credibility problem on the site. */
.cardgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px;margin:14px 0}
.card,.card-major{
  display:block;border:1px solid var(--line);border-radius:var(--radius);
  padding:18px 20px;text-decoration:none;color:inherit;background:var(--bg);
  transition:border-color .15s ease,box-shadow .15s ease;
}
.card-major{border-left:4px solid var(--o)}
.card:hover,.card-major:hover{border-color:var(--o);box-shadow:0 3px 14px rgba(28,25,23,.07)}
.card h3,.card-major h3{margin:0 0 5px;color:var(--ink);font-size:1.06rem;max-width:none}
.card p,.card-major p{margin:0;color:var(--mut);font-size:.92rem;max-width:none}

/* guides: a plain list, deliberately quieter than the review cards */
.minorlist{list-style:none;padding:0;margin:10px 0}
.minorlist li{border-bottom:1px solid var(--line);margin:0}
.minorlist li:last-child{border-bottom:0}
.minorlist a{
  display:block;padding:12px 2px;text-decoration:none;color:var(--ink);font-weight:500;
}
.minorlist a:hover{color:var(--o)}
.minorlist span{display:block;color:var(--mut);font-size:.9rem;font-weight:400;margin-top:2px}

.trust{
  background:var(--wash);border:1px solid var(--line);border-radius:12px;
  padding:18px 20px;margin:16px 0;color:var(--mut);font-size:.95rem;
}
.trust p{max-width:var(--measure)}

/* ---------- RAIL ---------- */
.pagegrid{max-width:1240px;margin:0 auto}
@media(min-width:1060px){
  .pagegrid{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:40px;align-items:start}
  .rail{position:sticky;top:76px;margin:26px 0 40px}   /* 76px clears the sticky header */
}
@media(max-width:1059px){.rail{display:none}}
.rail{font-size:.89rem}
.railbox{border:1px solid var(--line);border-radius:var(--radius);padding:16px 18px;background:var(--bg);margin:0 0 14px}
.railbox h3{margin:0 0 8px;font-size:1.02rem}
.railbox ul{margin:0;padding-left:18px}
.railbox li{margin:6px 0;max-width:none}
.railbox p{margin:0;line-height:1.6;max-width:none}
.railbox .prov{margin-top:10px;display:block;max-width:none}

/* ---------- STICKY BOTTOM CTA ---------- */
/* KEPT, against the advice from round 2, and the reason is on the record:
   DeepSeek argued to drop it because it makes the CTA permanently visible while the verdict
   is not. That is a good argument. But the click event never registered cta_text as a GA4
   custom dimension and linkText comes back empty, so across 90 days and 15 outbound clicks
   NOT ONE can be attributed to the sticky bar versus the in-page CTA. Dropping it blind could
   remove the element carrying most of our conversions, and we would never see it happen.
   So: instrument first (cta_position is now sent on every click), decide in 30 days with data.
   Measuring beats picking a side. */
.sticky{
  position:sticky;bottom:0;z-index:10;
  background:rgba(255,255,255,.96);backdrop-filter:blur(8px);
  border-top:1px solid var(--line);padding:10px 20px;text-align:center;
}
.sticky .cta{margin:0;padding:12px 24px}

/* ---------- MOBILE ---------- */
@media(max-width:768px){
  body{font-size:16px}
  .hero{padding:28px 18px 4px}
  .hero h1{font-size:1.72rem;max-width:none}
  .hero p{font-size:1.02rem}
  main{padding:8px 18px 70px}
  main h2,h2.section{font-size:1.28rem;margin:30px 0 8px}
  .verdict{padding:18px 18px}
  .verdict h2,.verdict .verdict-line{font-size:1.24rem;max-width:none}
  .cols{grid-template-columns:1fr}
  .cardgrid{grid-template-columns:1fr}
  input,textarea,select{font-size:16px}   /* stops iOS zoom-on-focus */
}
@media(max-width:640px){
  table{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch}
  h1{font-size:1.6rem;line-height:1.25}
  .sticky .cta,.sticky a{
    max-width:100%;white-space:normal;padding:11px 16px;
    font-size:.93rem;line-height:1.3;display:inline-block;
  }
}

/* ---------- ACCESSIBILITY ---------- */
a:focus-visible,.card:focus-visible,.card-major:focus-visible{outline:3px solid var(--o);outline-offset:2px}
@media(prefers-reduced-motion:reduce){
  *{animation:none !important;transition:none !important;scroll-behavior:auto !important}
}
/*mobfix*/

/* ---------- SHORT-VIEWPORT GUARD ---------- */
/* A sticky header plus a sticky bottom CTA together ate 25% of a 517px-tall window when
   measured. On short viewports the chrome shrinks so the content keeps the screen. */
@media(max-height:620px){
  header{padding:8px 20px}
  header .logo{font-size:1.08rem}
  .sticky{padding:7px 20px}
  .sticky .cta{padding:9px 20px;font-size:.92rem}
}
/* anchor links must not land under the sticky header */
:target,h2[id],h3[id],section[id]{scroll-margin-top:76px}

/* ---------- NARROW HEADER ---------- */
/* Measured at 390px: logo + three nav items overflow the row and "How we rate" wrapped onto a
   second line, splitting the nav in half. Below 520px the header becomes a deliberate two-row
   block instead of a broken one. */
@media(max-width:520px){
  header{padding:10px 18px}
  header .inner,.hdr-inner{flex-direction:column;align-items:flex-start;gap:6px}
  header .logo{font-size:1.1rem}
  header nav{display:flex;gap:16px}
  header nav a{margin-left:0;font-size:.84rem}
}

/* ---------- LEGACY MARKUP SUPPORT ---------- */
/* The 15 pages grew three different header shapes. Rather than rewrite page structure during
   migration - which risks the prose, the claims and the provenance lines - the stylesheet
   absorbs the variants. Markup stays untouched; only the <style> block is swapped for a <link>. */

/* form B: <header class="site"><div class="wrap"><a href="/">The Dryer Edit</a></div></header> */
header.site .wrap,header .wrap{
  max-width:var(--shell);margin:0 auto;
  /* padding:0 is load-bearing: the generic .wrap rule adds 20px, and the <header> already
     supplies its own 20px. Without this the logo sat 20px inside the content column. */
  padding:0;
  display:flex;justify-content:space-between;align-items:center;gap:16px;
}
/* The wordmark was rendering two different ways: six pages said "THE DRYER EDIT" and nine said
   "The Dryer Edit". Since being remembered BY NAME is the entire point of the social work, the
   brand should not have two appearances. Normalised in CSS rather than by editing the text in
   15 files - the markup keeps its natural casing for screen readers and copy-paste, and every
   page renders the same wordmark. */
header.site a,header > a.logo,header .logo{
  font-family:Georgia,"Times New Roman",serif;
  color:var(--ink);font-weight:700;font-size:1.22rem;
  text-transform:uppercase;letter-spacing:.06em;
  text-decoration:none;white-space:nowrap;
}
/* form A without an .inner wrapper: make the <header> itself the flex row */
header:not(:has(.inner)):not(:has(.wrap)){
  display:flex;justify-content:space-between;align-items:center;gap:16px;
}
@media(max-width:520px){
  header:not(:has(.inner)):not(:has(.wrap)){flex-direction:column;align-items:flex-start;gap:6px}
  header.site .wrap,header .wrap{flex-direction:column;align-items:flex-start;gap:6px}
}

/* content wrapper used by the older money pages */
.wrap{max-width:820px;margin:0 auto;padding:0 20px}
.pagegrid > .wrap{padding-left:20px;padding-right:0}
@media(max-width:1059px){.pagegrid > .wrap{padding-right:20px}}
.wrap p,.wrap li{max-width:var(--measure)}

/* breadcrumbs - chrome, so sans, and quiet */
.crumbs{
  font-family:Inter,system-ui,sans-serif;
  font-size:.83rem;color:var(--prov);margin:18px 0 6px;
}
.crumbs a{color:var(--prov);text-decoration:none}
.crumbs a:hover{color:var(--o);text-decoration:underline}

/* .tldr is the old name for the verdict block - same component, so same styling */
.tldr{
  border:1px solid var(--line);border-left:5px solid var(--o);
  border-radius:var(--radius);background:var(--bg);
  box-shadow:0 2px 14px rgba(28,25,23,.05);
  padding:22px 24px;margin:18px 0 26px;
}
.tldr .badge{
  display:inline-block;background:var(--badge);color:var(--o-dk);
  font-family:Inter,system-ui,sans-serif;font-weight:700;font-size:.76rem;
  letter-spacing:.03em;padding:4px 12px;border-radius:20px;
}
.tldr h2{font-size:1.42rem;line-height:1.3;margin:12px 0 6px;max-width:34ch}
.tldr .specs{font-family:Inter,system-ui,sans-serif;color:var(--mut);font-size:.94rem;margin:8px 0}
.tldr p{max-width:var(--measure)}

/* ---------- THREE-COLUMN PAGES (left rail + content + right rail) ---------- */
/* Three pages - bellforno-review, best-hair-dryer-under-60 and best-professional-hair-dryer-2026 -
   carried a second inline <style id="rails-css"> block with a two-rail layout. It was byte-identical
   on all three. The migration deliberately left it alone (its regex only matched a bare <style>),
   but leaving it inline meant the layout depended on source order against this file. Folded in here
   and scoped to .pagegrid:has(.railL), so only those pages get it and there is still one source of
   truth. Delete the inline block from those three pages once this is confirmed live. */
.pagegrid:has(.railL){max-width:1500px;padding:0 20px}
@media(min-width:1240px){
  .pagegrid:has(.railL){
    display:grid;grid-template-columns:230px minmax(0,1fr) 300px;gap:34px;align-items:start;
  }
  .pagegrid:has(.railL) > .railL{grid-column:1;grid-row:1}
  .pagegrid:has(.railL) > .wrap {grid-column:2;grid-row:1}
  .pagegrid:has(.railL) > .rail {grid-column:3;grid-row:1}
  .railL{position:sticky;top:76px;margin:26px 0 40px}
}
@media(min-width:1060px) and (max-width:1239px){
  .pagegrid:has(.railL){display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:30px;align-items:start}
  .railL{display:none}
}
@media(max-width:1059px){.railL{display:none}}
.railL{font-size:.89rem}
.railbox a{color:var(--ink)}
.railbox a:hover{color:var(--o)}
.railbox .here{font-weight:700;text-decoration:none;color:var(--bad)}

/* ---------- HEADER / GRID ALIGNMENT ---------- */
/* Measured bug, found at 1300px: the header bar is capped at --shell (900px) while the page
   grid is 1240px (or 1500px on the three-column pages). The logo therefore started at x=213
   while the content column and the left rail started at x=20 - a visible 190px misalignment
   on every page that shows a rail. The header container now matches the grid it sits above,
   at the same breakpoints the grid uses. Below 1060px there is no grid and the original
   centred 900px header is correct, so it is left alone. */
@media(min-width:1060px){
  body:has(.pagegrid) header .inner,
  body:has(.pagegrid) header .wrap{max-width:1240px}
}
@media(min-width:1240px){
  body:has(.railL) header .inner,
  body:has(.railL) header .wrap{max-width:1500px}
}
